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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

牛客多校3 - Operating on a Graph(并查集+链表合并)

發布時間:2024/4/11 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客多校3 - Operating on a Graph(并查集+链表合并) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個由 n 個點和 m 條邊組成的無向圖,每個點初始時都有顏色 i ,i ∈ [ 0 , n - 1 ] ,接下來有 q 次操作,每次操作會給出一種顏色 x ,分兩種情況討論:

  • 如果顏色為 x 的點不存在,則跳過此次操作
  • 如果顏色為 x 的點存在,則將顏色為 x 的點的相鄰的所有顏色塊,都染成 x 的顏色
  • 問最后每個點的顏色是什么

    題目分析:合并問題不難想到并查集,對于每個點的顏色可以用并查集來維護,不過如果暴力更新的話肯定會 T ,有一個比較顯然且比較重要的結論就是,每個點至多被遍歷一次,因為如果當某個點被遍歷過一次后,那么其相鄰的所有點肯定和當前的點都變為同一個顏色了,接下來無論如何操作,再遍歷這個點肯定是沒有任何進展的了,所以基于這個性質,我們可以用鏈表配合并查集實現模擬

    首先并查集的 f 數組配合 find 函數用來維護每個點被染成的顏色,初始化為每個點本身,其次每個顏色都建立一個鏈表,用來儲存當前顏色下有多少個點被染成了相同的顏色

    對于每一個詢問的顏色 x ,如果不存在的話,直接跳過即可,如果存在的話,可以遍歷一遍相應的鏈表進行擴展,根據上面的性質可知,遍歷過的元素直接刪除掉即可,對于新加入的元素,可以利用鏈表的 splice 方法,這個方法可以 O( 1 ) 合并兩個鏈表,如此一來,整體的時間復雜度也只是 O( n * a + m?),a 是并查集的時間開銷

    代碼:
    ?

    #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<list> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=8e5+100;list<int>li[N];vector<int>node[N];int f[N];void init(int n) {for(int i=0;i<n;i++){f[i]=i;li[i].clear();li[i].push_back(i);node[i].clear();} }int find(int x) {return x==f[x]?x:f[x]=find(f[x]); }void merge(int x,int y)//xx合并到yy {int xx=find(x);int yy=find(y);if(xx!=yy){f[xx]=yy;li[yy].splice(li[yy].end(),li[xx]);} }void update(int x) {if(x!=find(x))return;int sz=li[x].size();while(sz--){int u=li[x].front();li[x].pop_front();for(auto v:node[u])merge(v,u);} }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--){int n,m;scanf("%d%d",&n,&m);init(n);while(m--){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}int q;scanf("%d",&q);while(q--){int x;scanf("%d",&x);update(x);}for(int i=0;i<n;i++)printf("%d ",find(i));puts("");}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的牛客多校3 - Operating on a Graph(并查集+链表合并)的全部內容,希望文章能夠幫你解決所遇到的問題。

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