当前位置 博文首页 > 二十一岁的我:codeforce 01 - MST(补图连通块)

    二十一岁的我:codeforce 01 - MST(补图连通块)

    作者:[db:作者] 时间:2021-09-21 20:56

    题目链接

    题意:有一个完全图,然后权值只有0或者1,现在给你权值为1的边,其余权值为0,然后问你这个图的最小生成树的权值是多少。

    思路:很显然,我们要尽量多的用权值为0的边。这可怎么考虑呢?

    给的是权值为1的边可以形成一张图,这个图必定是原图的一个子图。然后这个子图的补图必定都是权值为0的边。

    我们可以考虑原图、补图转化的 思想。考虑补图(权值为0)的连通块个数。然后如果要把这些连通块连在一起的话,需要加权值为1 的边才行。

    所以答案 就是 补图的连通块个数 - 1

    #include<bits/stdc++.h>
    using namespace std;
    const int boss=2e5+10;
    unordered_map<int,bool> lj[boss];
    bitset<boss> b;
    int n,m,k,ans[boss];
    void dfs(int u)
    {
        b[u]=0,ans[k]++;
        for (int i=b._Find_first(); i<b.size(); i=b._Find_next(i))
            if (!lj[u][i])
                dfs(i);
    }
    int main()
    {
        int i;
        scanf("%d%d",&n,&m);
        for (i=1; i<=n; i++)
            b[i]=1;
        for (i=1; i<=m; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            lj[u][v]=lj[v][u]=1;
        }
        for (i=1; i<=n; i++)
            if (b[i])
                dfs(i),++k;
        printf("%d\n",k-1);
    }
    

    这里还有个神仙代码

    #include<bits/stdc++.h>
    using namespace std;
    const int boss=2e5+10;
    unordered_map<int,bool> lj[boss];
    bitset<boss> b;
    int n,m,k,ans[boss];
    void dfs(int u)
    {
        b[u]=0,ans[k]++;
        for (int i=b._Find_first(); i<b.size(); i=b._Find_next(i))
            if (!lj[u][i])
                dfs(i);
    }
    int main()
    {
        int i;
        scanf("%d%d",&n,&m);
        for (i=1; i<=n; i++)
            b[i]=1;
        for (i=1; i<=m; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            lj[u][v]=lj[v][u]=1;
        }
        for (i=1; i<=n; i++)
            if (b[i])
                dfs(i),++k;
        printf("%d\n",k-1);
    }
    

    ?

    cs