题解:

首先用最小生成树的方法来做一遍

然后枚举一下一些边可以被哪些边来替换

乘法原理计算总和

代码:

#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;
}

 

posted on 2017-10-17 21:25  宣毅鸣  阅读(...)  评论(... 编辑 收藏