这道题主要利用了最小生成树的两个性质
-
最小生成树每种边权的数目固定不变
-
最小生成树每种边权带来的连通状况一定唯一
由于每种边权的只有不到10种,所以直接穷举然后乘法原理即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.