题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1811
题目大意:给你一些ranking的比值关系,然后利用这些比值关系进行排名,让你确定是否能制作出排行榜,是的话就输出"OK",否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出"CONFLICT")。如果信息中同时包含冲突且信息不完全,就输出"CONFLICT"。
解题思路:
1、利用并查集操作,将相关联的 '=' 两边的数字先放存在一个集合里。
2、然后确定 ‘>’ , '<' 两边的数字是否和已存等号集合里的关系有重复,如果有直接输出"CONFLICT",否则建立领结表。这里要注意了,我就是在这里WA了一下午,因为等号关系已经确定,你现在要把存有具有相关联等号关系的数字的集合看做一个点,这里我们用每个集合的根节点代替。
3、开始拓扑排序,当拓扑排序完了遍历的节点小于n个,则可以说明拓扑过程中入度为0的节点没有n个,也就是拓扑序列中存在环。
4、当拓扑序列中同时出现两个或两个以上入度为0的节点时,说明信息不完全。
5、最后一种情况就只剩下满足的了。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<queue> 6 #include<cstdio> 7 using namespace std; 8 9 const int maxn=10005; 10 int deg[maxn]; 11 int father[maxn]; 12 int st[2*maxn]; 13 int sd[2*maxn]; 14 char ch[2*maxn]; 15 vector<int>vt[maxn]; 16 17 int find(int x) 18 { 19 while(x!=father[x]) 20 x=father[x]; 21 return x; 22 } 23 24 int main() 25 { 26 int n, m,u, v, fa, fb; 27 while(cin >> n >> m) 28 { 29 int flag=0, num=n; 30 for(int i=0; i<=n; i++) 31 vt[i].clear(), father[i]=i, deg[i]=0; 32 for(int i=0; i<m; i++) 33 { 34 scanf("%d %c %d",&st[i],&ch[i],&sd[i]); 35 if(ch[i]=='=') 36 { 37 fa=find(st[i]); 38 fb=find(sd[i]); 39 if(fa!=fb) 40 father[fb]=fa, num--; 41 } 42 } 43 for(int i=0; i<m; i++) 44 { 45 if(ch[i]=='>') 46 { 47 u=st[i], v=sd[i]; 48 fa=find(u); 49 fb=find(v); 50 if(fa==fb) flag=1; 51 deg[fb]++; 52 vt[fa].push_back(fb); 53 } 54 else if(ch[i]=='<') 55 { 56 u=st[i], v=sd[i]; 57 fa=find(u); 58 fb=find(v); 59 if(fa==fb) flag=1; 60 deg[fa]++; 61 vt[fb].push_back(fa); 62 } 63 } 64 if(flag) 65 { 66 puts("CONFLICT"); 67 continue; 68 } 69 int cnt=0; 70 queue<int>q; 71 for(int i=0; i<n; i++) 72 if(deg[i]==0&&i==find(i)) 73 q.push(i); 74 while(!q.empty()) 75 { 76 if(q.size()>1) flag=2; 77 int p=q.front(); 78 q.pop(); 79 num--; 80 for(int i=0; i<vt[p].size(); i++) 81 { 82 int v=vt[p][i]; 83 deg[v]--; 84 if(deg[v]==0) 85 q.push(v); 86 } 87 } 88 if(num>0) 89 puts("CONFLICT"); 90 else if(flag) 91 puts("UNCERTAIN"); 92 else 93 puts("OK"); 94 } 95 return 0; 96 }