hdu1811 Rank of Tetris 拓扑排序+并查集
这道题是拓扑排序和并查集的综合运用。
由于排行榜是一种从高到低的排序。所以在拓扑排序的时候,如果有一次加入的入度为零的点数大于1,就有变得不确定了(UNCERTAIN)。
由于只有一棵树,当树的数量大于1,就矛盾。还有一种产生矛盾的可能是,当输入的是a>b(或者a<b)时,但是并查集中他们的父节点相同。因为这题的一个集合其实被当成了一个点。这样不相等的相等就是矛盾的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N = 10010, M =20010; 7 struct node 8 { 9 int to, next; 10 }; 11 node edge[M]; 12 int ind[N], head[N],que[N],f[N],L[N],R[N]; 13 int iq,tot,num,FLAG; 14 char ch[N]; 15 int Find(int x) 16 { 17 if(x==f[x]) return x; 18 return f[x]=Find(f[x]); 19 } 20 void topo(int n) 21 { 22 int i,k,j=0,s; 23 for(i=0;i<n;i++) 24 if(ind[i]==0&&i==Find(i)) que[j++]=i; 25 FLAG=0; 26 if(j>1) FLAG=1; 27 s=j; 28 for(i=0;i<j;i++) 29 { 30 if(j-s>1) FLAG=1; 31 s=j; 32 int u=que[i]; 33 num--; 34 for(k=head[u]; k!=-1; k=edge[k].next) 35 { 36 ind[edge[k].to]--; 37 if(ind[edge[k].to]==0) 38 que[j++]=edge[k].to; 39 } 40 } 41 iq=j; 42 } 43 void addedge(int i,int j) 44 { 45 edge[tot].to=j;edge[tot].next=head[i];head[i]=tot++; 46 } 47 48 void Link(int i,int j) 49 { 50 int a=Find(i),b=Find(j); 51 if(a!=b) {f[b]=a;} 52 } 53 void init() 54 { 55 tot=0; 56 for(int i=0;i<N;i++) 57 { 58 f[i]=i; 59 head[i]=-1; 60 ind[i]=0; 61 } 62 } 63 int main() 64 { 65 //freopen("test.txt","r",stdin); 66 int n,m,i,j,k; 67 while(scanf("%d%d",&n,&m)!=EOF) 68 { 69 init(); 70 int flag=1; 71 num=n; 72 for(i=0;i<m;i++) 73 { 74 scanf("%d %c %d",&L[i],&ch[i],&R[i]); 75 if(ch[i]=='=') {Link(L[i],R[i]);num--;} 76 } 77 for(i=0;i<m;i++) 78 { 79 if(ch[i]=='=') continue; 80 int a=Find(L[i]),b=Find(R[i]); 81 if(a==b) flag=0; 82 if(ch[i]=='>') {addedge(a,b); ind[b]++;} 83 else {addedge(b,a); ind[a]++;} 84 } 85 topo(n); 86 if(num>1||!flag) printf("CONFLICT\n"); 87 else if(FLAG) printf("UNCERTAIN\n"); 88 else printf("OK\n"); 89 } 90 return 0; 91 }