• bzoj 1016 深搜


      首先我们知道MST的一些性质,对于这道题来说就是,假设我们先求出一颗MST设为G,由已知边权相同的边最多会有10条,那么假设我们在这10条边中选取size条边∈G,那么我们在这边权相同的边集E中任意选取size条有意义的边,这里的有意义的边的定义为每条边都会造成新的连通性的增加,那么边集E中所有的size条有意义的边的方案我们可以通过dfs求出,然后我们将不同边权的边的方案求连乘,就是MST的方案数。

      ps:我们没有必要求一遍MST,我们可以一边做kruskal,一边维护图的连通性,然后每找到一个权值不同的边集E时深搜。

      反思:做dfs的时候使用并查集维护图的连通性,但是加了路径压缩,这样就会在找块的祖先的时候改变不同节点的父亲,这样就没有办法在dfs时恢复原图,所以我们应该只用并查集维护节点的父亲而不是祖先,找了半天才找到这里的错误。

      

    /**************************************************************
        Problem: 1016
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:8 ms
        Memory:820 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 110
    #define maxm 1010
    #define d39 31011
     
    using namespace std;
     
    int n,m;
    int father[maxn],curfather[maxn];
    struct rec
    {
        int a,b,len;
    } c[maxm];
     
    bool cmp(rec a,rec b)
    {return (a.len<b.len);}
     
    int getfather(int x)
    {
        if (father[x]==x) return x;
        return father[x]=getfather(father[x]);
    }
     
    int getcurfather(int x)
    {
        if (curfather[x]==x) return x;
        return getcurfather(curfather[x]);
    }
     
    int dfs(int l,int r,int size)
    {
        //printf("%d %d %d
    ",l,r,size);
        if (!size) return 1;
        if (l>r) return 0;
        int fa,fb,cur=0;
        cur=dfs(l+1,r,size);
        fa=getcurfather(c[l].a); fb=getcurfather(c[l].b);
        if (fa!=fb)
        {
            curfather[fa]=fb;
            cur+=dfs(l+1,r,size-1);
            curfather[fa]=fa;
        }
        return cur;
    }
     
    int main()
    {
        int ans=1,cnt=0;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++) scanf("%d%d%d",&c[i].a,&c[i].b,&c[i].len);
        sort(c+1,c+m+1,cmp);
        for (int i=1;i<=n;i++) father[i]=curfather[i]=i;
        int cur=0;
        int l,r,size=0;
        for (int i=1;i<=m+1;i++)
        {
            if (cur!=c[i].len)
            {
                r=i-1;
                //if (i!=1) printf(" %d %d %d
    ",l,r,size);
                if (i!=1) ans=(ans*=dfs(l,r,size))%d39;
                l=i;
                size=0;
                cur=c[i].len;
                memcpy(curfather,father,sizeof curfather);
            }
            int fa,fb;
            fa=getfather(c[i].a); fb=getfather(c[i].b);
            if (fa!=fb)
            {
                size++;
                cnt++;
                father[fa]=fb;
            }
        }
        if (cnt!=n-1) printf("0
    "); else printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    人脸识别学习_01
    操作系统——第四章课后习题答案02
    知识就是力量,但更重要的是运用知识的能力网页端微信扫码支付技术设计
    java.net.ConnectException: Connect to XXXhost:XXXport failed: 拒绝连接 (Connection refused)
    web安全渗透扫描已解密的登录请求
    在jsp中显示原始html代码,不要渲染 / 在JSP页面中如何将HTML标记显示出来
    ThreadFactoryBuilder,它更好!
    【页面布局改造】今天,搞了个寂寞
    使用NSSM将.net core WebApi项目发布为windows服务(转载)
    NPM install 错误 : fatal: unable to connect to github.com 另类安装方法(转载)
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3551852.html
Copyright © 2020-2023  润新知