HDU1811 拓撲排序判環+並查集
阿新 • • 發佈:2017-07-22
const queue 根據 i++ 博客 我們 ret pre space
HDU Rank of Tetris
題目:http://acm.hdu.edu.cn/showproblem.php?pid=1811
題意:中文問題就不解釋題意了。
這道題其實就是一個拓撲排序判圈,我的博客裏面其他幾篇拓撲排序判圈的套路一樣。但是這道題與他們不同的的是在大小關系裏面存在一種 “=”的關系,這就意味的那些序號不同的點,實際上是一個點。共享入度和出度。我們可以通過並查集將他們合並,合成一個點。這裏說一下如何判斷信息不完全。我們早先在做拓撲排序,多種排列方式的時候,按照字典序輸出。我們建立一個優先隊列,維護字典序,這個時候堆裏是有很多元素的,我們通過優先隊列取出最小或者最大,實際上這些元素在拓撲排序中是等價關系,也就是說他們之間的大小關系無法比較。在這道題中,如果滯留在隊列中的元素超過一個說明有兩個元素無法比較的,就說明了答案是UNCLEARED。直接看代碼吧!,具體細節寫在註釋裏面了。
//Author: xiaowuga #include <bits/stdc++.h> #define maxx INT_MAX #define minn INT_MIN #define inf 0x3f3f3f3f const long long N=10000+10; using namespace std; typedef long long LL; vector<int>p[N]; int f[N]; int in[N]; struct node{ int x,y; char ch; }oj[N]; int n,m; int ct=0,flag=0; //並查集套路int Find(int x){ return f[x]==x?x:f[x]=Find(f[x]); } void topo(){ queue<int>q; while(!q.empty()) q.pop(); for(int i=0;i<n;i++) if(!in[i]&&Find(i)==i) q.push(i);//首先得是並查集中的根,然後出度為0 while(!q.empty()){ if(q.size()>1) flag=1;//同級元素大於一個說明有至少有兩個元素無法比較,所以信息不完全 intt=q.front();q.pop(); ct++; for(int i=0;i<p[t].size();i++){ int tmp=p[t][i]; if(--in[tmp]==0) q.push(tmp); } } if(ct!=n) cout<<"CONFLICT"<<endl; else if(flag) cout<<"UNCERTAIN"<<endl; else cout<<"OK"<<endl; } int main() { ios::sync_with_stdio(false);cin.tie(0); while(cin>>n>>m){ for(int i=0;i<n;i++) f[i]=i; memset(in,0,sizeof(in)); for(int i=0;i<n;i++) p[i].clear(); int x,y; ct=flag=0; //先處理‘=‘帶來的點的減少,建立並查集縮點 for(int i=0;i<m;i++){ cin>>oj[i].x>>oj[i].ch>>oj[i].y; if(oj[i].ch==‘=‘){ x=Find(oj[i].x); y=Find(oj[i].y); if(x!=y) {f[x]=y;ct++;}//縮點了別忘了ct++,因為相當於總點數減少了一個 } } //根據縮完點的點邊關系,反向建圖(正向建圖也可以) for(int i=0;i<m;i++){ if(oj[i].ch==‘=‘) continue; x=Find(oj[i].x); y=Find(oj[i].y); if(oj[i].ch==‘>‘){ p[y].push_back(x); in[x]++; } else{ p[x].push_back(y); in[y]++; } } //並查集處理完建圖之後就是常規的拓撲排序 topo(); } return 0; }
在最小生成樹的克魯斯卡爾算法裏,並查集被用來判斷是否形成環路,正如我在我的其他幾份博文裏面說的那樣,我認為在一個圖中,如果出現環,那麽環可以縮成一個點。環上的點實際上是等價的,也就是說並查集實際上是通過邊的關系,說明兩個不同的點,合並成一個點,通過一個根共享他們的信息。a=b全等價於a>b,a<b這樣兩條邊。我們根據這個信息把a,b合並。通過一個根可以是a,也可以是b來查詢這個整體的信息。總結一句並查集就是把一些不同的東西合並在一起,一起查詢的工具。
HDU1811 拓撲排序判環+並查集