[CF920E] Connected Components?

Description

给出一个 (n) 个点,(frac{n(n-1)}{2}-m) 的无向图,以补图的形式输入,问图中有多少连通分量以及每个连通分量有多少点。

Solution

考虑增量构造,依次加入每一个点,维护已有的连通块。对于每一个新加入的带点,考察其余某一个已有的连通块是否连通,这只需要数一下边的条数即可,如果连通则并查集维护一下。容易发现连通块数量一定是很小的。

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;

int fa[N],sz[N],n,m,t1,t2;
vector <int> g[N];

int find(int p)
{
    return p==fa[p] ? p : fa[p]=find(fa[p]);
}

set<int> s;

void merge(int p,int q)
{
    p=find(p);
    q=find(q);
    if(p>q) swap(p,q);
    if(p!=q) sz[q]+=sz[p],fa[p]=q;
}

signed main()
{
    //ios::sync_with_stdio(false);

    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
        sz[i]=1;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>t1>>t2;
        if(t1>t2) swap(t1,t2);
        g[t2].push_back(t1);
    }

    for(int i=1;i<=n;i++)
    {
        map<int,int> mp;
        for(int j:g[i])
        {
            mp[find(j)]++;
        }
        vector <int> vec;
        for(int j:s)
        {
            if(find(j)==j && mp[j]<sz[j])
            {
                vec.push_back(j);
            }
        }
        for(int j:vec)
        {
            merge(i,j);
        }
        vec.clear();
        for(int j:s)
        {
            if(find(j)!=j) vec.push_back(j);
        }
        for(int j:vec)
        {
            s.erase(j);
        }
        if(find(i)==i) s.insert(i);
        /*for(int j:s)
        {
            cout<<j<<",";
        }
        cout<<endl;*/
    }

    multiset <int> ans;
    for(int i:s)
    {
        ans.insert(sz[i]);
    }
    cout<<ans.size()<<endl;
    for(int i:ans)
    {
        cout<<i<<" ";
    }
}

原文地址:https://www.cnblogs.com/mollnn/p/13637026.html