[JSOI2008]最小生成树计数
[JSOI2008]最小生成树计数
时间限制: 1 Sec 内存限制: 162 MB
题目描述
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的
最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生
成树可能很多,所以你只需要输出方案数对31011的模就可以了。输入
第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整
数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,0
00。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。输出
输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。
样例输入
4 6 1 2 1 1 3 1 1 4 1 2 3 2 2 4 1 3 4 1
样例输出
8
Solution:
表示并不会Matrix-Tree,直接暴力就好了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 #define mod 31011 7 #define N 105 8 #define M 1005 9 int read() { 10 int s=0,f=1; 11 char ch=getchar(); 12 for( ; ch<'0'||ch>'9'; f=(ch=='-')?-1:f,ch=getchar()) ; 13 for( ; ch>='0'&&ch<='9'; s=s*10+(ch^48),ch=getchar()) ; 14 return s*f; 15 } 16 int n,m,Ans=1; 17 struct EDGE { 18 int fr,to,w; 19 friend bool operator < (EDGE a,EDGE b) {return a.w<b.w;} 20 } Edge[M]; 21 struct MST { 22 int Fa[N]; 23 int find(int x) {return Fa[x]==x?x:Fa[x]=find(Fa[x]);} 24 void init() {for(int i=1; i<=n; ++i) Fa[i]=i;} 25 int Count() { 26 int ans=0; 27 for(int i=1; i<=n; ++i) if(Fa[i]==i) ++ans; 28 return ans; 29 } 30 bool Union(int x,int y) { 31 int fx=find(x),fy=find(y); 32 if(fx!=fy) Fa[fx]=fy; 33 return fx!=fy; 34 } 35 } A,B,C; 36 int main() { 37 //freopen("bzoj_1016.in","r",stdin); 38 //freopen("bzoj_1016.out","w",stdout); 39 n=read(),m=read(); 40 if(m<n-1) {puts("0"); return 0;} 41 for(int x,y,z,i=1; i<=m; ++i) Edge[i]=(EDGE){x=read(),y=read(),z=read()}; 42 sort(Edge+1,Edge+m+1); A.init(),C.init(); 43 for(int begin=1,Q=1,cnt,len; Q<=m; ++Q) { 44 if(Q==m||Edge[Q].w!=Edge[Q+1].w) { 45 for(int i=begin; i<=Q; ++i) C.Union(Edge[i].fr,Edge[i].to); 46 len=Q-begin+1; cnt=0; 47 for(int State=0; State<(1<<len); ++State) { 48 int now=1; 49 for(int i=1; i<=n; ++i) B.Fa[i]=A.Fa[i]; 50 for(int i=1; i<=len; ++i) { 51 if(State&(1<<(i-1))) { 52 int U=Edge[i+begin-1].fr,V=Edge[i+begin-1].to; 53 if(!B.Union(U,V)) {now=0; break;} 54 } 55 } if(now) if(C.Count()!=B.Count()) now=0; 56 cnt+=now; 57 } Ans=(Ans*cnt)%mod; 58 for(int i=1; i<=n; ++i) A.Fa[i]=C.Fa[i]; 59 begin=Q+1; 60 } 61 } printf("%d",Ans); 62 return 0; 63 }