题意:现在有一个排名系统,有一系列信息,分别是 > < = 的比较,而如果最终相等,就会将这些相等的按照序号从小到大排,问给出的信息是否可以确定完整的排序。
由于如果很多点相等,他们肯定能够确定名次,那么我们只要让他们共同拥有与其他点的大小关系就行了。所以就用到了并查集,将相等的点加入并查集,再对并查集排拓扑序,如果能够排出唯一的拓扑序,那么在每个并查集内部也能够有唯一的顺序。
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 }
时间: 2024-10-08 18:08:11