• bzoj1098


    并查集+dfs

    先开始想和不相连的点用并查集连起来,最后看每个连通块有多少个点就行了,但是这样是O(n*n)的,然而我并没有想到补图

    其实就是求补图有多少连通块,因为补图中两个点有边,那么这两个点必须在一栋大楼里,因为他们之间没有联系,然后这样就有了许多连通块,不同的连通块可以不相连,因为不同的连通块之间没有边,也就是不同的连通块的点之间都有联系,然后我们只要求出这样的连通块的数量和大小。

    但是补图太稠密,不能直接求,然后我们就要用奇技淫巧来优化,我们用并查集维护每个点,用并查集维护下一个没有用过的点是哪个,然后我们dfs,用并查集查询下一个没有访问过的点,然后判断当前的点和那个点在原图中是否相连,相连的话说明这两个点在补图中没有边,没有必要访问,因为两个点或许不在一个连通块内,而且两个点在补图中不相连,自然不会访问。如果一个点已经被访问,那么自然不会再次访问,于是,每个点访问一次,边访问一次,复杂度O(n+m)

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    int n, m, cnt;
    int fa[N], ans[N];
    vector<int> G[N];
    inline int read()
    {
        int x = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
        while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
    int find(int x)
    {
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    }
    void dfs(int u)
    {
        ++ans[cnt];
        fa[u] = find(u + 1);
        for(int i = find(1); i <= n; i = find(i + 1))
        {
            bool flag = true;
            for(int j = 0; j < G[u].size(); ++j)
            {
                int v = G[u][j];
                if(v == i) 
                {
                    flag = false;
                    break;
                }
            }
            if(flag) dfs(i);
        }
    }
    int main()
    {
        n = read();
        m = read();
        for(int i = 1; i <= m; ++i)
        {
            int u = read(), v = read();
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for(int i = 1; i <= n + 1; ++i) fa[i] = i;
        for(int i = 1; i <= n; ++i) if(fa[i] == i)
        {
            ++cnt;
            dfs(i);
        }
        printf("%d
    ", cnt);
        sort(ans + 1, ans + cnt + 1);
        for(int i = 1; i <= cnt; ++i) printf("%d ", ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    【iOS开发】协议与委托 (Protocol and Delegate) 实例解析(转)
    Axure例——双击显示
    联动下拉菜单应用
    VB 9.0 和C# 3.0比较
    Office VBA进阶(二):如何在Access 2007里导入一个Excel sheet表
    Static Code Analysis Introduction
    VB future
    Office VBA进阶(三):如何合并Access里的多张表
    Office VBA进阶(四):如何在Access里创建一个Report
    Office VBA进阶(五):如何让EXCEL工作簿在浏览器里显示
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7294450.html
Copyright © 2020-2023  润新知