现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的
最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生
成树可能很多,所以你只需要输出方案数对31011的模就可以了。
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的
最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生
成树可能很多,所以你只需要输出方案数对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的模就可以了。
不懂如何求解,当成模板收集下来慢慢理解.....
/* http://blog.csdn.net/liuke19950717 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=105; const int mod=31011; int n,m,sum; int fa[maxn]; struct edge { int x,y,len; }e[maxn*10]; struct data { int l,r,len; }a[maxn*10]; bool cmp(edge a,edge b) { return a.len<b.len; } int find(int x) { return x==fa[x]?x:find(fa[x]); } void dfs(int x,int now,int k) { if(now==a[x].r+1) { if(k==a[x].len) { ++sum; } return ; } int p=find(e[now].x),q=find(e[now].y); if(p!=q) { fa[p]=q; dfs(x,now+1,k+1); fa[p]=p;fa[q]=q; } dfs(x,now+1,k); } void init(int n) { for(int i=1;i<=n;++i) { fa[i]=i; } } int main() { while(~scanf("%d%d",&n,&m)) { init(n); memset(a,0,sizeof(a)); int ans=1,cnt=0,tot=0; for(int i=1;i<=m;++i) { scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].len);//边的权值 } sort(e+1,e+m+1,cmp); for(int i=1;i<=m;++i) { if(e[i].len!=e[i-1].len) { a[++cnt].l=i; a[cnt-1].r=i-1; } int p=find(e[i].x),q=find(e[i].y); if(p!=q) { fa[p]=q; a[cnt].len++; tot++; } } a[cnt].r=m; if(tot!=n-1) { printf("0"); return 0; } init(n); for(int i=1;i<=cnt;++i) { sum=0; dfs(i,a[i].l,0); ans=(ans*sum)%mod; for(int j=a[i].l;j<=a[i].r;++j) { int p=find(e[j].x),q=find(e[j].y); if(p!=q) { fa[p]=q; } } } printf("%d\n",ans); } return 0; }