HDU 1811 Rank of Tetris(並查集+拓撲排序 非常經典)
阿新 • • 發佈:2018-10-24
memory max scan ble tput col turn 排行榜 行動
為了更好的符合那些愛好者的喜好,Lele又想了一個新點子:他將制作一個全球Tetris高手排行榜,定時更新,名堂要比福布斯富豪榜還響。關於如何排名,這個不用說都知道是根據Rating從高到低來排,如果兩個人具有相同的Rating,那就按這幾個人的RP從高到低來排。
終於,Lele要開始行動了,對N個人進行排名。為了方便起見,每個人都已經被編號,分別從0到N-1,並且編號越大,RP就越高。
同時Lele從狗仔隊裏取得一些(M個)關於Rating的信息。這些信息可能有三種情況,分別是"A > B","A = B","A < B",分別表示A的Rating高於B,等於B,小於B。
現在Lele並不是讓你來幫他制作這個高手榜,他只是想知道,根據這些信息是否能夠確定出這個高手榜,是的話就輸出"OK"。否則就請你判斷出錯的原因,到底是因為信息不完全(輸出"UNCERTAIN"),還是因為這些信息中包含沖突(輸出"CONFLICT")。
註意,如果信息中同時包含沖突且信息不完全,就輸出"CONFLICT"。
Input
本題目包含多組測試,請處理到文件結束。
每組測試第一行包含兩個整數N,M(0<=N<=10000,0<=M<=20000),分別表示要排名的人數以及得到的關系數。
接下來有M行,分別表示這些關系
Author
linle
Rank of Tetris
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12344 Accepted Submission(s): 3497
為了更好的符合那些愛好者的喜好,Lele又想了一個新點子:他將制作一個全球Tetris高手排行榜,定時更新,名堂要比福布斯富豪榜還響。關於如何排名,這個不用說都知道是根據Rating從高到低來排,如果兩個人具有相同的Rating,那就按這幾個人的RP從高到低來排。
終於,Lele要開始行動了,對N個人進行排名。為了方便起見,每個人都已經被編號,分別從0到N-1,並且編號越大,RP就越高。
同時Lele從狗仔隊裏取得一些(M個)關於Rating的信息。這些信息可能有三種情況,分別是"A > B","A = B","A < B",分別表示A的Rating高於B,等於B,小於B。
現在Lele並不是讓你來幫他制作這個高手榜,他只是想知道,根據這些信息是否能夠確定出這個高手榜,是的話就輸出"OK"。否則就請你判斷出錯的原因,到底是因為信息不完全(輸出"UNCERTAIN"),還是因為這些信息中包含沖突(輸出"CONFLICT")。
註意,如果信息中同時包含沖突且信息不完全,就輸出"CONFLICT"。
每組測試第一行包含兩個整數N,M(0<=N<=10000,0<=M<=20000),分別表示要排名的人數以及得到的關系數。
接下來有M行,分別表示這些關系
Output 對於每組測試,在一行裏按題目要求輸出
Sample Input 3 3 0 > 1 1 < 2 0 > 2 4 4 1 = 2 1 > 3 2 > 0 0 > 1 3 3 1 > 0 1 > 2 2 < 1
Sample Output OK CONFLICT UNCERTAIN
Source HDOJ 2007 Summer Exercise(2)
Recommend lcy | We have carefully selected several similar problems for you: 1558 1879 1863 1875 1823 分析: 如果直接拓撲的話,等號的情況很麻煩 一.采用並查集處理=號的情況 把具有等號關系的點聚合成為一個連通分量,且只用該連通分量的根結點替代分量中的所有點 比如A=B=C=D 以後A,B,C,D這四個點就只用A來表示 需要註意的地方: 1.必須先處理完所有的等號之後再進行拓撲排序(最後才想到!!!) 2.因為存在等號,我們有把等號處理了,所有我們可以拓撲的點可能不是n個了,而是根結點的個數個 2.采用拓撲排序處理>和<的情況 ps: 沖突情況:存在環,也就是進入隊列的點不等於可以拓撲的點 信息不完全:某時刻隊列裏面元素個數大於1個,說明圖不是連通圖 必須先處理完所有等號的情況才能進行拓撲!!! wa好多次
#include<stdio.h> #include<iostream> #include<math.h> #include<string.h> #include<set> #include<map> #include<list> #include<queue> #include<algorithm> using namespace std; typedef long long LL; int mon1[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int mon2[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31}; int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}}; int getval() { int ret(0); char c; while((c=getchar())==‘ ‘||c==‘\n‘||c==‘\r‘); ret=c-‘0‘; while((c=getchar())!=‘ ‘&&c!=‘\n‘&&c!=‘\r‘) ret=ret*10+c-‘0‘; return ret; } #define max_v 20005 int pa[max_v]; int rk[max_v]; int indgree[max_v]; int a[max_v],b[max_v]; char o[max_v]; queue<int> q; vector<int> vv[max_v]; int n,m,cnt; int fa_num; void init() { for(int i=0; i<=n; i++) pa[i]=i,rk[i]=0; memset(indgree,0,sizeof(indgree)); while(!q.empty()) q.pop(); for(int i=0; i<=n; i++) vv[i].clear(); fa_num=0; cnt=0; } int find_set(int x) { if(x!=pa[x]) pa[x]=find_set(pa[x]); return pa[x]; } void union_set(int x,int y) { x=find_set(x); y=find_set(y); if(x==y) return ; if(rk[x]>rk[y]) pa[y]=x; else { pa[x]=y; if(rk[x]==rk[y]) rk[y]++; } } int tpsort() { for(int i=1; i<=n; i++) { if(find_set(i)==i)//拓撲點必須是根結點 { fa_num++;//計數 根結點 if(indgree[i]==0) q.push(i); } } int temp; int flag=0; while(!q.empty()) { if(q.size()>1) flag=1;//信息不完全 temp=q.front(); q.pop(); cnt++; for(int i=0; i<vv[temp].size(); i++) { indgree[find_set(vv[temp][i])]--; if(indgree[find_set(vv[temp][i])]==0) q.push(find_set(vv[temp][i])); } } if(flag)//不能全拓撲(整個圖不是連通的) return 1; else return 0; } int main() { int x,y; char c; while(~scanf("%d %d",&n,&m)) { if(n==1&&m==0) { printf("OK\n"); continue; } init(); int flag1=0;//沖突 1 int flag2=0;//信息不完全 1 for(int i=1; i<=m; i++)//必須先合並除去=號,不能邊除去邊拓撲!!! { getchar(); scanf("%d %c %d",&a[i],&c,&b[i]); a[i]++,b[i]++; o[i]=c; if(c==‘=‘) { union_set(a[i],b[i]); } } for(int i=1;i<=m;i++) { if(o[i]==‘=‘) continue; x=find_set(a[i]); y=find_set(b[i]); if(o[i]!=‘=‘&&find_set(x)==find_set(y)) { flag1=1; continue; } if(o[i]==‘<‘) { int temp=x; x=y; y=temp; } if(count(vv[y].begin(),vv[y].end(),x)!=0)//環的一種情況 { flag1=1; } if(count(vv[x].begin(),vv[x].end(),y)==0)//預防重邊 { vv[x].push_back(y); indgree[y]++; } } flag2=tpsort(); if(cnt!=fa_num)//不能全排列拓撲,因為信息不全 flag1=1; if(flag1==0&&flag2==0) { printf("OK\n"); } else if(flag1==1&&flag2==1) { printf("CONFLICT\n"); } else if(flag2==1&&flag1==0) { printf("UNCERTAIN\n"); } else if(flag1==1&&flag2==0) { printf("CONFLICT\n"); } } return 0; }
HDU 1811 Rank of Tetris(並查集+拓撲排序 非常經典)