標籤:style blog http color os io ar for art
【原題】
http://acm.hdu.edu.cn/showproblem.php?pid=1811
【類型】
並查集+拓撲排序
【題意】
給定一些點對之間的關係(大於小於相等),判斷是否發生衝突。
【分析】
對於衝突判斷,直觀的想法就是拓撲排序。以大於符號或者小於符號方向作為拓撲序的方向,如果處理時出現違反拓撲序列的情況則可判斷為衝突。
然後這道題還有另外一個問題就是相等情況的處理,如果直接按照拓撲排序對其進行分析,則可能發生錯誤。為瞭解決這個問題,可以用並查集進行預先處理,將所有相等的點縮成1個點,然後進行後序的拓撲排序。
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int father[10001]; void clean_father(int n){ for (int i=0;i<n;i++) father[i]=i;} int getfather(int x){ if (father[x]!=x) father[x]=getfather(father[x]); return father[x];}void link(int x,int y){ father[getfather(x)]=getfather(y);} int x[20001],y[20001],rd[10001],num[10001],start[10001];char z[20001];typedef struct { int a,b;} node;node a[20001];bool op(node a,node b){ return a.a<b.a;}int stack[10001];int main(){ int n,m; while (scanf("%d%d",&n,&m)!=EOF) { clean_father(n); for (int i=1;i<=m;i++) { scanf("%d %c %d",&x[i],&z[i],&y[i]); if (z[i]==‘=‘) link(x[i],y[i]); } int tail=0; for (int i=0;i<n;i++) rd[i]=-1; int tot=0; for (int i=0;i<n;i++) { rd[getfather(i)]=0; if (rd[i]==0) tot++; } for (int i=1;i<=m;i++) switch(z[i]) { case ‘>‘: tail++; a[tail].a=getfather(x[i]); a[tail].b=getfather(y[i]); rd[getfather(y[i])]++; break; case ‘<‘: tail++; a[tail].a=getfather(y[i]); a[tail].b=getfather(x[i]); rd[getfather(x[i])]++; } sort(&a[1],&a[tail+1],op); int o=-1; for (int i=0;i<n;i++) num[i]=0; for (int i=1;i<=tail;i++) { if (a[i].a!=o) { o=a[i].a; start[o]=i; } num[o]++; } int top=0; for (int i=0;i<n;i++) if (rd[i]==0) { top++; stack[top]=i; } if (top==0) { printf("CONFLICT\n"); continue; } bool flag=false,done=false; while (top>0&&(!done)) { if (top>1) flag=true; int now=stack[top]; top--;tot--; for (int i=0;i<num[now];i++) { rd[a[start[now]+i].b]--; if (rd[a[start[now]+i].b]==0) { top++; stack[top]=a[start[now]+i].b; } else if (rd[a[start[now]+i].b]<0) { done=true; break; } } num[now]=0; } if (tot>0||done) printf("CONFLICT\n"); else if (flag) printf("UNCERTAIN\n"); else printf("OK\n"); } return 0;}View Code
1811 Rank of Tetris