【HDOJ1811】【并查集预处理+拓扑排序】
http://acm.hdu.edu.cn/showproblem.php?pid=1811
Rank of Tetris
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11382 Accepted Submission(s): 3261
Problem Description
自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球。
为了更好的符合那些爱好者的喜好,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"。
为了更好的符合那些爱好者的喜好,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行,分别表示这些关系
每组测试第一行包含两个整数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
题目大意:给一堆点的关系【大于小于或等于】让判断这些点之间的关系是否明确【任何两个点的关系都能确定】且正确【不会出现冲突】
题目分析:首先预处理:大于和小于容易处理,直接当作有向边就行,而等于应用并查集进行预处理使等于的关系点缩成连通块【这和强连通分量Tarjan缩点类似】,
预处理完之后将各连通块按照关系进行有向连接,
最后根据入度、出度以及拓扑序列中点的个数来确定是否正确。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 queue<int>pq; 7 struct edge{ 8 int to; 9 int next; 10 }EDGE[20005]; 11 struct pot{ 12 int to1; 13 int to2; 14 char ch; 15 }POT[20005]; 16 int cnt=0; 17 int flag; 18 int in[10005],head[10005],pre[10005],vis[10005],vviss[10005],vvis[10005],out[10005]; 19 int n,m,N; 20 void add(int x,int y) 21 { 22 in[y]++; 23 out[x]++; 24 EDGE[cnt].to=y; 25 EDGE[cnt].next=head[x]; 26 head[x]=cnt++; 27 } 28 int orz1=0,orz2=0; 29 int find(int x) 30 { 31 int xx=x; 32 while(x!=pre[x]) 33 { 34 x=pre[x]; 35 } 36 while(pre[xx]!=x) 37 { 38 int t=pre[xx]; 39 pre[xx]=x; 40 xx=t; 41 } 42 return x; 43 } 44 void Topsort() 45 { 46 int wqw=0; 47 for(int i = 0 ; i < N ; i++) 48 { 49 if(!in[find(i)]&&!vis[find(i)]) 50 { 51 wqw++; 52 orz2++; 53 vis[find(i)]=1; 54 pq.push(find(i)); 55 } 56 } 57 if(wqw>1)flag=2; 58 while(!pq.empty()) 59 { 60 int qwq=pq.front();pq.pop(); 61 for(int i = head[qwq];i != -1 ; i=EDGE[i].next) 62 { 63 int v=EDGE[i].to; 64 in[v]--; 65 if(!in[v]) 66 { 67 orz2++; 68 pq.push(v); 69 } 70 } 71 } 72 } 73 int main() 74 { 75 while(scanf("%d%d",&n,&m)==2) 76 { 77 N=n; 78 orz1=0;orz2=0; 79 memset(head,-1,sizeof(head)); 80 memset(vis,0,sizeof(vis)); 81 memset(vvis,0,sizeof(vvis)); 82 memset(vviss,0,sizeof(vviss)); 83 memset(in,0,sizeof(in)); 84 memset(out,0,sizeof(out)); 85 for(int i = 0 ; i < n ; i++)pre[i]=i; 86 for(int i = 0 ; i < m; i++) 87 { 88 int a,c; 89 char b; 90 scanf("%d %c %d",&POT[i].to1,&POT[i].ch,&POT[i].to2); 91 if(POT[i].ch=='=') 92 { 93 if(find(POT[i].to1)!=find(POT[i].to2)) 94 { 95 pre[find(POT[i].to1)]=find(POT[i].to2); 96 n--; 97 } 98 // vviss[find(POT[i].to2)]=1; 99 } 100 } 101 flag=0; 102 for(int i = 0 ; i < m ; i++) 103 { 104 if(POT[i].ch=='=') 105 continue; 106 char b=POT[i].ch; 107 int a=find(POT[i].to1); 108 int c=find(POT[i].to2); 109 if(a!=c) 110 { 111 if(b=='>') 112 add(a,c); 113 else if(b=='<') 114 add(c,a); 115 116 } 117 else 118 flag=3; 119 } 120 int qwq=0; 121 if(flag!=3) 122 { 123 for(int i = 0 ; i < N ; i++) 124 { 125 if(!out[find(i)]&&!vvis[find(i)]) 126 { 127 vvis[find(i)]=1; 128 qwq++; 129 if(qwq>1){ 130 flag=2; 131 break;} 132 } 133 } 134 Topsort(); 135 if(orz2<n)flag=3; 136 } 137 if(flag==2)printf("UNCERTAIN\n"); 138 else if(flag==3)printf("CONFLICT\n"); 139 else printf("OK\n"); 140 } 141 142 return 0; 143 }