最小生成树计数(有一个神奇的操作)

有一个定理:无论最小生成树由哪些边组成,其中使用的每种边权的边的数量是一定的

所以由此我们可以得到一种做法:记录最小生成树使用的每种边的数量,然后dfs使用这些边去构建另一棵最小生成树

#include<bits/stdc++.h>
using namespace std;
const int mod=31011;
int n,m,sum;
struct node{
    int x,y,w;
}e[9999999];
struct Node{
    int l,r,len;
}a[9999999];
int pre[9999999];
bool cmp(node a,node b){
    return a.w<b.w;
}
void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
void print(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9){print(x/10);}
    putchar(x%10+'0');
}
int find(int x)
{
    //return x==pre[x]?x:pre[x]=find(pre[x]); //写成x:pre[x]=find(pre[x]);不对 
    return x==pre[x]?x:find(pre[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){
        pre[p]=q;
        dfs(x,now+1,k+1);
        pre[p]=p;pre[q]=q;
    }
    dfs(x,now+1,k);
}
int main()
{
    read(n),read(m);
    for(register int i=1;i<=n;++i) pre[i]=i;
    int tot=0,cnt=0,ans=1;    
    for(register int i=1;i<=m;i++)
        read(e[i].x),read(e[i].y),read(e[i].w);
    sort(e+1,e+m+1,cmp);
    for(register int i=1;i<=m;++i)
    {
        if(e[i].w!=e[i-1].w)
        {
            a[++cnt].l=i;
            a[cnt-1].r=i-1;
        }
        int p=find(e[i].x);
        int q=find(e[i].y);
        if(p!=q)
        {
            pre[p]=q;
            a[cnt].len++;
            tot++;
        }
    }
    a[cnt].r=m;
    if(tot!=n-1){
        putchar('0');return 0;
    }
    for(register int i=1;i<=n;i++) pre[i]=i;
    for(register int i=1;i<=cnt;++i)
    {
        sum=0;
        dfs(i,a[i].l,0);
        ans=(ans*sum)%mod;
        for(register int j=a[i].l;j<=a[i].r;++j)
        {
            int p=find(e[j].x),q=find(e[j].y);
            if(p!=q){
                pre[p]=q;
            }
        }
    }
    print(ans);
    return 0;
}

 

posted @ 2018-08-26 17:26  南柯一场  阅读(425)  评论(0编辑  收藏  举报