题意:现在有一个排名系统,有一系列信息,分别是 > < = 的比较,而如果最终相等,就会将这些相等的按照序号从小到大排,问给出的信息是否可以确定完整的排序。
由于如果很多点相等,他们肯定能够确定名次,那么我们只要让他们共同拥有与其他点的大小关系就行了。所以就用到了并查集,将相等的点加入并查集,再对并查集排拓扑序,如果能够排出唯一的拓扑序,那么在每个并查集内部也能够有唯一的顺序。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h>
2 #include<string.h>
3 #include<queue>
4 using namespace std;
5 const int maxn=1e4+5;
6 const int maxm=2e4+5;
7
8 int fa[maxn],num,n;
9 int a[maxm],b[maxm];
10 char c[maxm][10];
11 int head[maxn],point[maxm],nxt[maxm],size;
12 int id[maxn];
13
14 void init(){for(int i=0;i<n;++i)fa[i]=i;}
15
16 int find(int x){
17 int r=x,t;
18 while(r!=fa[r])r=fa[r];
19 while(x!=r){
20 t=fa[x];
21 fa[x]=r;
22 x=t;
23 }
24 return r;
25 }
26
27 int topo(){
28 queue<int>q;
29 bool f=1;
30 for(int i=0;i<n;++i)if(fa[i]==i&&!id[i])q.push(i);
31 int cnt=0;
32 while(!q.empty()){
33 int u=q.front();
34 q.pop();
35 cnt++;
36 if(!q.empty())f=0;
37 for(int i=head[u];~i;i=nxt[i]){
38 int j=point[i];
39 id[j]--;
40 if(!id[j])q.push(j);
41 }
42 }
43 if(cnt!=num)return 0;
44 if(f)return 1;
45 return -1;
46 }
47
48 void add(int a,int b){
49 point[size]=b;
50 nxt[size]=head[a];
51 head[a]=size++;
52 id[b]++;
53 }
54
55 int main(){
56 int m;
57 while(scanf("%d%d",&n,&m)!=EOF){
58 memset(id,0,sizeof(id));
59 memset(head,-1,sizeof(head));
60 size=0;
61 init();
62 num=n;
63 for(int i=1;i<=m;++i){
64 scanf("%d%s%d",&a[i],c[i],&b[i]);
65 if(c[i][0]=='='){
66 int x=find(a[i]),y=find(b[i]);
67 if(x!=y){
68 fa[x]=y;
69 num--;
70 }
71 }
72 }
73 for(int i=1;i<=m;++i){
74 if(c[i][0]=='>'){
75 add(find(a[i]),find(b[i]));
76 }
77 else if(c[i][0]=='<'){
78 add(find(b[i]),find(a[i]));
79 }
80 }
81 int tmp=topo();
82 if(tmp==1)printf("OK\n");
83 else if(tmp==0)printf("CONFLICT\n");
84 else if(tmp==-1)printf("UNCERTAIN\n");
85 }
86 }