E. Connected Components (BFS )

  • 题目链接:http://codeforces.com/contest/920/problem/E
  • 题意:给你n个点,m条边,这个由n个点组成的图中,除了给你的m条边不存在以外,其他边都存在,两点间只有一条边,且无自环。
  • 算法:BFS
  • 思路:因为1 ≤ n ≤ 200000,所以用无法用邻接表存图,可以用二维的map代替二维数组(当然,既然算法是BFS的话,用前向星之类的也行)。
    • 把1~n放入一个点集,
    • 从一个点开始BFS,找出所有与该点连在一起的点,并把这些点从点集中删去,同时记录下他们的个数。循环这一步操作,直到点集为空。
  • 坑点:这题看起来用set比较简单,但是set在寻找连通点的时候太麻烦
    • 删去已经找到的点后,如何让迭代器获得新的点的位置?毕竟将当前点删去后,迭代器指向的当前点的值。如果用upper_bound()更新的话,如果当前点是set中最后一个值的话又会出问题。所以本文用的是vector

#include <bits/stdc++.h>
#define pi acos(-1)
#define fastcin ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const LL ll_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 200000 + 10;
const int mod = 1e9 + 7;


map<int, bool> mp[maxn];
vector<int> vec, ans;


int BFS(int x)
{
    queue<int> Q;
    Q.push(x);
    int cnt=0;
    while(!Q.empty()){
        int u = Q.front(); Q.pop();
        cnt++;
        for(int i=0; i<vec.size(); i++){
            x = vec[i];
            if(!mp[u][x]){
                Q.push(vec[i]);
                swap(vec[i], vec.back()); vec.pop_back();
                i--;
            }
        }
    }
    return cnt;
}


int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i=0; i<m; i++){
        int x,y;
        scanf("%d%d", &x, &y);
        mp[x][y]=1;
        mp[y][x]=1;
    }
    for(int i=1; i<=n; i++) vec.push_back(i);
    while(!vec.empty()){
        int x = vec.back(); vec.pop_back();
        int each = BFS(x);
        if(each) ans.push_back(each);
    }
    sort(ans.begin(), ans.end());
    printf("%d\n", ans.size());
    for(int i=0; i<ans.size(); i++){
        printf("%d%c", ans[i], " \n"[i==ans.size()-1]);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37352710/article/details/80262844