CodeForces - 920E_Connected Components? 模拟

题目大意:无向图中给定n个顶点,m条不存在的边(除了这m条边,其余都存在),求图的连通分量,及每个连通分量的大小。

list < int > g;存储1~n个顶点。再后续的操作中将其分裂成若干块,直到list为空。
(1)当list不为空,清空队列,取队首的一个点入队。
(2)当queue不为空,取一个点,将与其相关的点入队并从list中删除。记录联通块大小。

#include 
#include 
#include 
#include 
#include 

using namespace std;
const int N = 2e5+10;
bool vis[N];
vector <int> a[N], ans;
list <int> g;//用vector超时
list <int>:: iterator it, tmp;
int n, m;

int main()
{
    scanf("%d %d", &n, &m);
    int x, y;
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d %d", &x, &y);
        a[x].push_back(y);
        a[y].push_back(x);
    }
    for(int i = 1; i <= n; ++i) g.push_back(i);//分裂g成若干个联通块
    while(!g.empty())//一次得到一个联通块,直到分裂完毕即为空
    {
        ans.push_back(1);
        queue <int> q;
        it = g.begin();
        q.push((*it));
        g.erase(it);//分裂
        while(!q.empty())//用入队的点继续扩展
        {
            memset(vis, 0, sizeof(vis));
            int u = q.front();
            q.pop();
            for(int i = 0; i < a[u].size(); ++i)
                vis[a[u][i]] = 1;//标记于u无关的点
            for(it = g.begin(); it != g.end();)
                if(!vis[(*it)])//与u有关的点
                {
                    ++ans.back();
                    q.push((*it));
                    tmp = it;
                    ++it;//先++再删点
                    g.erase(tmp);//分裂
                }
                else ++it;//
        }
    }
    sort(ans.begin(), ans.end());
    printf("%d\n", ans.size());
    printf("%d", ans[0]);
    for(int i = 1; i < ans.size(); ++i)
        printf(" %d", ans[i]);
    printf("\n");
    return 0;
}

你可能感兴趣的:(模拟)