日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【CodeForces - 920E】Connected Components? (dsu,补图连通块,STLset+map,bfs 或bitset)

發布時間:2023/12/10 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【CodeForces - 920E】Connected Components? (dsu,补图连通块,STLset+map,bfs 或bitset) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:

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

題目大意:

無向圖中給定n個頂點,m條不存在的邊(除了這m條邊,其余都存在),求圖的連通分量,及每個連通分量的大小。

解題報告:

官方題解:

別從給定的邊入手,而是直接對所有頂點bfs就可以了,可以證明復雜度是線性的,頂多加上容器自帶的log。

當然, 其實用不到upperbound,因為bfs就是邊刪除邊進行的,不會涉及迭代器危機。但是dfs就比較危險了,下面代碼就有對應官方題解的dfs。

AC代碼1:(240ms)

vector維護當前還剩多少點沒有被訪問到(注意巧妙的O1維護方式,正常的維護需要On的時間)。map記錄邊的信息

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; map<int,bool> mp[MAX]; vector<int> vv,ans; int bfs(int x) {int res = 0;queue<int> q;q.push(x);while(q.size()) {int cur = q.front();q.pop();res++; // int up = vv.size();這里不能這樣寫,因為size是動態的。for(int i = 0; i<(int)vv.size(); i++) {int v = vv[i];if(mp[cur].count(v) == 0) {swap(vv[i],vv.back());//用來實現set的erase操作,減少常數。 vv.pop_back();//用來實現set的erase操作 i--;q.push(v);}}}return res; } int main() {int n,m;cin>>n>>m;for(int i = 1; i<=n; i++) vv.pb(i);for(int x,y,i = 1; i<=m; i++) {scanf("%d%d",&x,&y);mp[x][y]=1;mp[y][x]=1;}while(!vv.empty()) {int v = vv.back();vv.pop_back();int cnt = bfs(v);ans.push_back(cnt);}sort(ans.begin(),ans.end());printf("%d\n",ans.size());for(int i = 0; i<(int)ans.size(); i++) {printf("%d ",ans[i]);}return 0 ; }

?

AC代碼2:

用set維護未被訪問的點集,bfs中對于每一個點,先一遍操作,同時記錄一個vector,然后再更新到set中(刪除元素),這樣避免了邊操作邊更新所帶來的迭代器的變化,避免了 不好控制 的情況發生。

?

AC代碼3:

用map<int,set<int> > mp? 來減小內存。(實際上也無所謂,直接開2e5個set一樣的)

注意dfs中,用pair來接受一個map,也就是這里ip其實代表的就是一個pair。

這里也掌握一種姿勢:就算是遇到AC代碼2那種? set迭代器的問題的時候,第一可以用AC代碼2那種處理方式,第二可以改用map:如果需要刪除it,那就先將it記錄到tmp中,然后刪除it,然后再upperbound一下就可以了。

AC代碼4:

bitset維護未訪問的點集。

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #include<bitset> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; set<int> ss[MAX]; bitset<MAX> bs; int n,m,ans[MAX],tot; void dfs(int x) {bs[x] = 0;ans[tot]++;for(int i = bs._Find_first(); i<bs.size(); i = bs._Find_next(i)) {if(ss[x].count(i) == 0) dfs(i);} } int main() {cin>>n>>m;for(int i = 1; i<=n; i++) bs[i] = 1;for(int u,v,i = 1; i<=m; i++) {scanf("%d%d",&u,&v);ss[u].insert(v);ss[v].insert(u);}for(int i = 1; i<=n; i++) {if(bs[i]) tot++,dfs(i);}printf("%d\n",tot);sort(ans+1,ans+tot+1);for(int i = 1; i<=tot; i++) {printf("%d%c",ans[i],i == tot ? '\n' : ' ');}return 0 ; }

貼一個更快的:

AC代碼5:

//別人的代碼 #include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; set<int>st; vector<int> mp[MAX]; int ans[MAX]; int del[MAX]; int n,m,tot; void Bfs(int x) {tot++;ans[tot]=1;st.erase(x);queue<int>s;s.push(x);while(!s.empty()) {int u=s.front();s.pop();int cnt=0;for(set<int>::iterator it=st.begin(); it!=st.end(); it++) {int to=*it;if(binary_search(mp[u].begin(),mp[u].end(),to) == 0) {s.push(to);ans[tot]++;del[++cnt]=to;}}for(int i=1; i<=cnt; i++)st.erase(del[i]);} } int main() {scanf("%d%d",&n,&m);tot=0;st.clear();for(int i=1; i<=m; i++) {int x,y;scanf("%d%d",&x,&y);mp[x].push_back(y);mp[y].push_back(x);}for(int i=1; i<=n; i++)st.insert(i),sort(mp[i].begin(),mp[i].end());for(int i=1; i<=n; i++) {if(st.count(i))Bfs(i);}printf("%d\n",tot);sort(ans+1,ans+tot+1);for(int i=1; i<=tot; i++) {printf("%d ",ans[i]);} }

總結

以上是生活随笔為你收集整理的【CodeForces - 920E】Connected Components? (dsu,补图连通块,STLset+map,bfs 或bitset)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。