標籤:g++ ... 就是 i+1 tab table include return nlog
題目連結:https://cn.vjudge.net/problem/CodeForces-920E
題意
給一個補圖,問各個聯通塊有幾個元素,升序排列
注意maxn=2e5, maxm=2e10
思路
資料量超大,這本來是並查集專題的一道題
如果用並查集的話,向上維護一個元素個數,但首先離線建圖是個問題O(n^2)
這樣考慮的話,bfs O(n)就是更好的選擇
提交上去TLE,當時寫題沒仔細算複雜度,set查邊+數組判重,加起來貌似O(nlogn+n),至於為什麼用set查邊,因為數組查邊肯定空間太大
最後查了查題解,判重是鏈表刪除元素,相當於真正的刪除了,迴圈次數大大降低了
好麼,厲害
提交過程
CE |
標頭檔 |
TLE1 |
set<pair<int, int>>存邊 |
TLE2 |
改成set |
WA1-3 |
忘了為啥WA了... |
AC |
|
代碼
#include <set>#include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=2e5+20;int n, m, cnt, size[maxn], next[maxn], prev[maxn];bool check[maxn];set<long long> vis;void del(int x){ next[prev[x]]=next[x]; prev[next[x]]=prev[x];}int bfs(int x){ int ans=1; queue<int> que; que.push(x); check[x]=true; del(x); while (que.size()){ int node=que.front(); que.pop(); for (int i=next[0]; i<=n; i=next[i]) if (!check[i] && !vis.count((long long)i*maxn+node)){ que.push(i); check[i]=true; del(i); ans++; } }return ans;}int main(void){ int to, from; scanf("%d%d", &n, &m); for (int i=0; i<m; i++){ scanf("%d%d", &to, &from); vis.insert((long long)to*maxn+from); vis.insert((long long)from*maxn+to); } for (int i=1; i<=n; i++) next[i]=i+1, prev[i]=i-1; next[0]=1; prev[n+1]=n; int cnt=0; for (int i=1; i<=n; i++) if (!check[i]) size[cnt++]=bfs(i); sort(size, size+cnt); printf("%d\n", cnt); for (int i=0; i<cnt; i++) printf("%d%c", size[i], " \n"[i==cnt-1]); return 0;}
Time |
Memory |
Length |
Lang |
Submitted |
343ms |
16012kB |
1067 |
GNU G++ 5.1.0 |
2018-07-23 17:51:00 |
CodeForces-920E Connected Components? 廣度搜尋 判斷聯通 大量資料下重複點的刪除