zoukankan      html  css  js  c++  java
  • P4208 [JSOI2008]最小生成树计数

    思路

    刚看到的时候,因为 ((nleq 100)) ,所以想到了爆搜,但是这样做显然会 (TLE) ,所以我们手摸几组数据找找结论

    然后能发现一个结论:一张图上的不同最小生成树中,权值相等的边的个数是不变的

    小证明:用kruskal求最小生成树时,每一步都是最优的,如果有不同的最小生成树,则当前步的权值必然小于等于之前最小生成树当前步的选择。但是反证可得,如果有小于的话,此时的最小生成树就比之前的优了,和之前矛盾,所以权值相等的边的个数是不变的。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int mod=31011;
    struct node{
        int from,to,w;
    }e[1010];
    struct kruskal{
        int l,r,v;
    }a[1010];//存i边的个数,l r是左右端点,v是i在最小生成树上的个数
    int n,m,f[110],ans,q[110],num,sum;
    
    int find(int x){return x==f[x]?x:find(f[x]);}
    //不能路径压缩!!!
    
    bool cmp(node a,node b){
        return a.w<b.w;
    }
    
    void dfs(int x,int now,int k)//x是你当前找的值 now是第几个边 k是你选了的个数
    {
        if(now==a[x].r+1){
            if(k==a[x].v) sum++;//保证和生成树所需的一样
            return ;
        }
        int xx=find(e[now].from),yy=find(e[now].to);
        if(xx!=yy)//看是否选这边就为环
        {
            f[xx]=yy;
            dfs(x,now+1,k+1);//选
            f[xx]=xx;f[yy]=yy;//复原
        }
        dfs(x,now+1,k);//不选
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w);
        sort(e+1,e+m+1,cmp);
        int tot=0;
        for(int i=1;i<=m;i++){
            if(e[i].w!=e[i-1].w) num++,a[num].l=i,a[num-1].r=i-1;
            int xx=find(e[i].from),yy=find(e[i].to);
            if(xx!=yy) f[xx]=yy,a[num].v++,tot++;
        }//kruskal
        if(tot!=n-1){
            printf("0");
            return 0;
        }//如果构不成树,就可以输出0了
        a[num].r=m;
        ans=1;
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=1;i<=num;i++){
            sum=0;
            dfs(i,a[i].l,0);
            ans=(ans*sum)%mod;
            for(int j=a[i].l;j<=a[i].r;j++){
                int xx=find(e[j].from),yy=find(e[j].to);
                if(xx!=yy) f[xx]=yy;
            }//弄完一个后,连起来保证不为环
        }
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    openldap
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P1567 统计天数
    Java实现 洛谷 P1567 统计天数
  • 原文地址:https://www.cnblogs.com/jasony/p/13543213.html
Copyright © 2011-2022 走看看