Connected Components? CodeForces - 920E(求补图连通块)

You are given an undirected graph consisting of n vertices and edges. Instead of giving you the edges that exist in the graph, we give you m unordered pairs (x, y) such that there is no edge between x and y, and if some pair of vertices is not listed in the input, then there is an edge between these vertices.

You have to find the number of connected components in the graph and the size of each component. A connected component is a set of vertices X such that for every two vertices from this set there exists at least one path in the graph connecting these vertices, but adding any other vertex to X violates this rule.

Input
The first line contains two integers n and m (1 ≤ n ≤ 200000, ).

Then m lines follow, each containing a pair of integers x and y (1 ≤ x, y ≤ n, x ≠ y) denoting that there is no edge between x and y. Each pair is listed at most once; (x, y) and (y, x) are considered the same (so they are never listed in the same test). If some pair of vertices is not listed in the input, then there exists an edge between those vertices.

Output
Firstly print k — the number of connected components in this graph.

Then print k integers — the sizes of components. You should output these integers in non-descending order.

Example
Input
5 5
1 2
3 4
3 2
4 2
2 5
Output
2
1 4
Sponsor

题意:
给出n个点m条边的无向图。求其补图的连通块数目。

思路:
BZOJ1098原题。

两点有边就意味着是一个连通块,算连通块的常规算法是dfs或bfs。

那么此处用bfs,遍历x的所有出边,那么这些连接x的点与x均不想连,则所有剩余的点与x相连,这些点再放入队列继续算。

使用set或者链表来维护剩余的点。

每个点只会遍历一次,那么最坏情况是一个点遍历了m条边,其他点每个再遍历一次,复杂度为O(n + m)。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 2e5 + 7;
vector<int>G[maxn];
int vis[maxn],uncn[maxn],ans[maxn];
int lst[maxn],nex[maxn];
queue<int>Q;

void del(int x)
{
    nex[lst[x]] = nex[x];lst[nex[x]] = lst[x];
}

int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        G[x].push_back(y);G[y].push_back(x);
    }
    for(int i = 1;i < n;i++)
    {
        nex[i] = i + 1;lst[i + 1] = i;
    }
    nex[0] = 1;
    
    int cnt = 0;
    for(int i = 1;i <= n;i++)
    {
        if(vis[i] == 0)
        {
            ans[++cnt] = 1;vis[i] = 1;
            Q.push(i);del(i);
            while(!Q.empty())
            {
                int now = Q.front();Q.pop();
                for(int j = 0;j < G[now].size();j++)
                {
                    int v = G[now][j];
                    if(vis[v] == 0)uncn[v] = 1;
                }
                for(int j = nex[0];j;j = nex[j])
                {
                    if(uncn[j] == 0)
                    {
                        vis[j] = 1;ans[cnt]++;del(j);
                        Q.push(j);
                    }
                    else uncn[j] = 0;
                }
            }
        }
    }
    sort(ans + 1,ans + 1 + cnt);
    printf("%d\n",cnt);
    for(int i = 1;i <= cnt;i++)printf("%d ",ans[i]);
    return 0;
}



发布了697 篇原创文章 · 获赞 22 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/104294752