题解:
首先用最小生成树的方法来做一遍
然后枚举一下一些边可以被哪些边来替换
乘法原理计算总和
代码:
#include<bits/stdc++.h> const int M=31011; using namespace std; int n,m,cnt,tot,ans=1,sum,fa[105]; struct edge { int x,y,z; }e[1005]; struct data { int l,r,v; }a[1005]; bool cmp(edge a,edge b) { return a.z<b.z; } 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].v)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); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++)fa[i]=i; for (int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); sort(e+1,e+m+1,cmp); for (int i=1;i<=m;i++) { if(e[i].z!=e[i-1].z){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].v++;tot++;} } a[cnt].r=m; if(tot!=n-1) { puts("0"); return 0; } for (int i=1;i<=n;i++)fa[i]=i; for (int i=1;i<=cnt;i++) { sum=0; dfs(i,a[i].l,0); ans=(ans*sum)%M; 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",ans); return 0; }