题目:
题解:
并查集不能压缩路径,因为这样回溯时就不能直接还原了
代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define Mod 31011
using namespace std;
struct hh
{
int a,b,c;
}no[1005],pm[1005];
int f[105],hs,qz[1005],n,m,xz[1005];
int cmp(hh a,hh b){return a.c<b.c;}
int find(int x)
{
if (f[x]!=x) return find(f[x]);
return f[x];
}
void dfs(int zz,int be,int vv)
{
if (vv>qz[zz]) return;
if (be>pm[zz].b)
{
if (vv==qz[zz])
hs++,hs%=Mod;
return;
}
int x=find(no[be].a),y=find(no[be].b);
if (x!=y){f[x]=y; xz[be]=1; dfs(zz,be+1,vv+1); xz[be]=0;f[x]=x;}
dfs(zz,be+1,vv);
}
int main()
{
int i,maxx=0,zl=0,ans=1,tot=0,j;
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
scanf("%d%d%d",&no[i].a,&no[i].b,&no[i].c);
sort(no+1,no+m+1,cmp);
for (i=1;i<=n;i++) f[i]=i;
for (i=1;i<=m;i++)
{
if (no[i].c!=no[i-1].c)
pm[++zl].a=i,pm[zl-1].b=i-1;//起点
int x=find(no[i].a),y=find(no[i].b);
if (x!=y)
f[x]=y,qz[zl]++,tot++;
}
pm[zl].b=m;
if (tot!=n-1){printf("0");return 0;}
for (i=1;i<=n;i++) f[i]=i;
for (i=1;i<=zl;i++)
if (qz[i])
{
hs=0;
dfs(i,pm[i].a,0);
ans=ans*hs%Mod;
for (j=pm[i].a;j<=pm[i].b;j++)//每一种权值连完后效果一样
{
int x=find(no[j].a),y=find(no[j].b);
if (x!=y) f[x]=y;
}
}
printf("%d",ans%Mod);
}