欢迎使用CSDN-markdown编辑器

来源:互联网 发布:微信 淘客 软件 编辑:程序博客网 时间:2024/05/17 04:07

//先求一遍最小生成树,算出每种权值用了多少条边,枚举每种权值的方案数再相乘即可

#include <cstdio>#include <algorithm>#define maxn 1005#define mod 31011using namespace std;struct xx{    int u,v,q;}b[maxn];struct yy{    int l,r,g;}a[maxn];int ans=1,sum,f[maxn],h,p,t,n,m,head[105],g,x,y,z;bool bo;bool cmp(xx A,xx B){    return A.q<B.q;}int father(int n){return n==f[n]?n:father(f[n]);}//这里注意不要压缩路径int dfs(int x,int now,int k){    if (k==a[x].r+1){        if (a[x].g==now) sum++;        return 0;    }    if (now>a[x].g)return 0;    int p=father(b[k].u),q=father(b[k].v);    if (p!=q)    {        f[p]=q;        dfs(x,now+1,k+1);        f[p]=p;f[q]=q;    }    dfs(x,now,k+1);}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=m;i++)    {        scanf("%d%d%d",&x,&y,&z);        b[i]=(xx){x,y,z};//xx(x, y, z)    }    for (int i=1;i<=n;i++) f[i]=i;    sort(b+1,b+m+1,cmp);    for (int i=1;i<=m;i++)    {        if (b[i].q!=b[i-1].q) a[++g].l=i,a[g-1].r=i-1;        int t1=father(b[i].u),t2=father(b[i].v);        if (t1!=t2) {            f[t1]=t2;            a[g].g++;            p++;        }    }    a[g].r=m;    if (p!=n-1){        printf("0");        return 0;    }    for (int i=1;i<=n;i++) f[i]=i;    for (int i=1;i<=g;i++)    {        sum=0;        dfs(i,0,a[i].l);        ans=(ans*sum)%mod;        for (int j=a[i].l;j<=a[i].r;j++)          {            int t1=father(b[j].u),t2=father(b[j].v);            if (t1!=t2) f[t1]=t2;          }    }    printf("%d",ans);    return 0;}
0 0