随笔 - 540  文章 - 0 评论 - 39 trackbacks - 0

这道题主要利用了最小生成树的两个性质

  1. 最小生成树每种边权的数目固定不变

  2. 最小生成树每种边权带来的连通状况一定唯一

由于每种边权的只有不到10种,所以直接穷举然后乘法原理即可

  1 const mo=31011;
  2 type node=record
  3        x,y,w:longint;
  4      end;
  5 
  6 var a:array[0..10010] of node;
  7     fa,rank,v:array[0..10010] of longint;
  8     sum,ans,k1,k2,s,i,j,n,m,p,k:longint;
  9 
 10 function getf(x:longint):longint;
 11   begin
 12     if fa[x]<>x then fa[x]:=getf(fa[x]);
 13     exit(fa[x]);
 14   end;
 15 
 16 
 17 procedure swap(var a,b:node);
 18   var c:node;
 19   begin
 20     c:=a;
 21     a:=b;
 22     b:=c;
 23   end;
 24 
 25 procedure sort(l,r:longint);
 26   var i,j,x,y:longint;
 27   begin
 28     i:=l;
 29     j:=r;
 30     x:=a[(l+r) shr 1].w;
 31     repeat
 32       while a[i].w<x do inc(i);
 33       while x<a[j].w do dec(j);
 34       if not(i>j) then
 35       begin
 36         swap(a[i],a[j]);
 37         inc(i);
 38         j:=j-1;
 39       end;
 40     until i>j;
 41     if l<j then sort(l,j);
 42     if i<r then sort(i,r);
 43   end;
 44 
 45 function calc(x:longint):longint;
 46   begin
 47     calc:=0;
 48     while x>0 do
 49     begin
 50       calc:=calc+x mod 2;
 51       x:=x shr 1;
 52     end;
 53   end;
 54 
 55 function check(p,cur:longint):longint;
 56   var i,res,tot:longint;
 57   begin
 58     for i:=1 to n do
 59       fa[i]:=i;
 60     tot:=0;
 61     res:=0;
 62     for i:=p to j-1 do
 63     begin
 64       if cur and 1=1 then
 65       begin
 66         k1:=getf(a[i].x);
 67         k2:=getf(a[i].y);
 68         if k1<>k2 then
 69         begin
 70           fa[k1]:=k2;
 71           inc(tot);
 72           res:=res+a[i].w;
 73         end;
 74       end;
 75       cur:=cur shr 1;
 76     end;
 77     for i:=1 to m do
 78     begin
 79       if a[i].w=a[j-1].w then continue;
 80       k1:=getf(a[i].x);
 81       k2:=getf(a[i].y);
 82       if k1<>k2 then
 83       begin
 84         fa[k1]:=k2;
 85         inc(tot);
 86         res:=res+a[i].w;
 87       end;
 88     end;
 89     if (res=sum) and (tot=n-1) then exit(1) else exit(0);
 90   end;
 91 
 92 begin
 93   readln(n,m);
 94   for i:=1 to m do
 95     readln(a[i].x,a[i].y,a[i].w);
 96   sort(1,m);
 97   for i:=1 to n do
 98     fa[i]:=i;
 99   rank[1]:=1;
100   p:=1;
101   for i:=2 to m do
102   begin
103     if a[i].w<>a[i-1].w then inc(p);
104     rank[i]:=p;
105   end;
106   i:=0;
107   j:=0;
108   while i<n-1 do
109   begin
110     inc(j);
111     k1:=getf(a[j].x);
112     k2:=getf(a[j].y);
113     if k1<>k2 then
114     begin
115       fa[k1]:=k2;
116       inc(i);
117       inc(v[rank[j]]);
118       sum:=sum+a[j].w;
119     end;
120   end;
121   if i<n-1 then
122   begin
123     writeln(0);
124     halt;
125   end;
126   ans:=1;
127   i:=1;
128   while i<=m do
129   begin
130     j:=i+1;
131     while a[i].w=a[j].w do inc(j);
132     if v[rank[i]]>0 then
133     begin
134       s:=0;
135       for k:=0 to 1 shl (j-i)-1 do
136         if calc(k)=v[rank[i]] then s:=s+check(i,k);
137       ans:=ans*s mod mo;
138     end;
139     i:=j;
140   end;
141   writeln(ans);
142 end.
View Code

 

posted on 2014-09-05 21:43  acphile  阅读(...)  评论(... 编辑 收藏