[CF920E] Connected Components? - 思維,並查集,STL
阿新 • • 發佈:2020-09-09
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<<" "; } }