【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)
1016: [JSOI2008]最小生成树计数
Description
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的
最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生
成树可能很多,所以你只需要输出方案数对31011的模就可以了。Input
第一行包含两个数,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条。Output
输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。
Sample Input
4 6
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1Sample Output
8HINT
Source
【分析】
不知道结论是不可以做的吧?表示也不会矩阵树定理。。dfs方法也要知道一些证明才能说明其准确性。
【以后的博客都要留坑了?
安利两种题解:
1、我的打法:(不看都不知道为什么这样做是对的)
https://blog.sengxian.com/solutions/bzoj-1016
http://www.cnblogs.com/lcf-2000/p/5575412.html
2、矩阵树(没打这种,还不会)
http://blog.csdn.net/jarily/article/details/8902509
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 1100 8 #define Maxm 10100 9 #define Mod 31011 10 11 struct node 12 { 13 int x,y,c; 14 }t[Maxm]; 15 16 bool cmp(node x,node y) {return x.c<y.c;} 17 int a[Maxm],l[Maxm],r[Maxm],fa[Maxn]; 18 19 int ffa(int x) 20 { 21 return x==fa[x]?x:ffa(fa[x]); 22 } 23 24 int ct; 25 void ffind(int x,int nw,int h) 26 { 27 if(nw==r[x]+1) 28 { 29 if(h==a[x]) ct++; 30 return; 31 } 32 int x1=ffa(t[nw].x),x2=ffa(t[nw].y); 33 if(x1!=x2) 34 { 35 fa[x1]=x2; 36 ffind(x,nw+1,h+1); 37 fa[x1]=x1; 38 } 39 ffind(x,nw+1,h); 40 } 41 42 int main() 43 { 44 int n,m; 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=m;i++) 47 { 48 scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].c); 49 } 50 sort(t+1,t+1+m,cmp); 51 int cnt=0,tot=0; 52 for(int i=1;i<=n;i++) fa[i]=i; 53 for(int i=1;i<=m;i++) 54 { 55 if(i==1||t[i].c!=t[i-1].c) 56 { 57 r[cnt]=i-1;l[++cnt]=i; 58 a[cnt]=0; 59 } 60 int x1=ffa(t[i].x),x2=ffa(t[i].y); 61 if(x1!=x2) 62 { 63 fa[x1]=x2; 64 a[cnt]++; 65 tot++; 66 } 67 68 }r[cnt]=m; 69 if(tot!=n-1) printf("0\n"); 70 else 71 { 72 for(int i=1;i<=n;i++) fa[i]=i; 73 int ans=1; 74 for(int i=1;i<=cnt;i++) 75 { 76 ct=0; 77 ffind(i,l[i],0); 78 ct%=Mod; 79 ans=ans*ct;ans%=Mod; 80 for(int j=l[i];j<=r[i];j++) 81 { 82 int x1=ffa(t[j].x),x2=ffa(t[j].y); 83 if(x1!=x2) fa[x1]=x2; 84 } 85 } 86 printf("%d\n",ans); 87 } 88 return 0; 89 }
2017-02-28 13:58:04