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 1
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1
Sample Output
8
首先要知道一个定理,就是在最小生成树中,边权相等的边的数目是固定的。。。
我觉得就是u到v如果存在两条最短路径,如果边权不等的话,那么一定能找到一条更短的路径。。。
然后对每个边权dfs即可。。。
然后答案用乘法原理。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 10000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int fa[maxn],n,m,sum,cnt,tot,ans=1; 24 struct edge{ 25 int u,v,w; 26 }e[maxm]; 27 struct data{ 28 int l,r,v; 29 }a[maxn]; 30 bool cmp(edge a,edge b){ 31 return a.w<b.w; 32 } 33 int find(int x){ 34 if(fa[x]!=x)return find(fa[x]); 35 else return x; 36 } 37 void dfs(int x,int now,int k){ 38 if(now==a[x].r+1){ 39 if(k==a[x].v)sum++; 40 return; 41 } 42 int fau=find(e[now].u),fav=find(e[now].v); 43 if(fau!=fav){ 44 fa[fav]=fau; 45 dfs(x,now+1,k+1); 46 fa[fav]=fav;fa[fau]=fau; 47 } 48 dfs(x,now+1,k); 49 } 50 int read(){ 51 int x=0,f=1;char ch=getchar(); 52 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 53 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 54 return x*f; 55 } 56 int main(){ 57 //freopen("input.txt","r",stdin); 58 //freopen("output.txt","w",stdout); 59 n=read();m=read(); 60 for1(i,n)fa[i]=i; 61 for1(i,m){ 62 e[i].u=read();e[i].v=read();e[i].w=read(); 63 } 64 sort(1+e,e+m+1,cmp); 65 for1(i,m){ 66 if(e[i].w!=e[i-1].w){a[++cnt].l=i;a[cnt-1].r=i-1;} 67 int fau=find(e[i].u),fav=find(e[i].v); 68 if(fau!=fav){ 69 fa[fav]=fau;a[cnt].v++;tot++; 70 } 71 } 72 for1(i,n)fa[i]=i; 73 a[cnt].r=m; 74 if(tot!=n-1){printf("0");return 0;} 75 for1(i,cnt){ 76 sum=0; 77 dfs(i,a[i].l,0); 78 ans=(ans*sum)%31011; 79 for(int j=a[i].l;j<=a[i].r;j++){ 80 int fau=find(e[j].u),fav=find(e[j].v); 81 if(fau!=fav)fa[fav]=fau; 82 } 83 } 84 printf("%d",ans%31011); 85 return 0; 86 }