这道题WA了两天 - - !
思路:首先分析以下什么情况下才能OK(当然时可以判断出顺序的情况下),
CONFLICT(1就是存在等号并且有再>或<下情况存在所以一定时冲突的,2在开始统计并将度为0的点进入队列,同时要判断一下i==f[i]的点的个数,是否和即将全部出队列的个数一致);
UNCERTAIN(当入度为0 的个数>1{其中有两部分1,在开始压队列的时候判断一次,2再队列中删除度后再判断一次} )
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<map> #include<algorithm> #include<queue> #define ll long long #define inf 0x3f3f3f3f using namespace std; int cnt; struct node { int to,next; } q[20010]; int l[20010],r[20010]; char s[20010]; int du[20010],head[20010],f[20010]; int n,m; int fi(int x) { return x==f[x]?x:f[x]=fi(f[x]); } void mer(int a,int b) { int x=fi(a); int y=fi(b); f[x]=y; } void add(int x,int y) { q[cnt].to=y; q[cnt].next=head[x]; head[x]=cnt++; } int topo() { int j,k,i; queue<int >Q; int tot,tmp,flag; tot=tmp=flag=0; for(i=0;i<n;i++) { if(i==f[i]) { tot++; if(!du[i]) { tmp++; Q.push(i); } if(tmp>1) flag=2; } } k=0; while(!Q.empty()) { int t=Q.front(); Q.pop(); k++; //du[t]--; tmp=0; for(j=head[t];j!=-1;j=q[j].next) { du[ q[j].to ]--; if(!du[q[j].to ]) { tmp++; Q.push(q[j].to); } } if(tmp>1) flag=2; } if(k<tot) flag=1; return flag; } int Map() { int i,x,y; for(i=0;i<n;i++) f[i]=i; for(i=0;i<m;i++) { scanf("%d %c %d",&l[i],&s[i],&r[i]); if(s[i]=='=') { x=fi(l[i]); y=fi(r[i]); f[x]=y; } } memset(head,-1,sizeof(head)); memset(du,0,sizeof(du)); cnt=0; for(i=0;i<m;i++) { if(s[i]=='=') continue; x=fi(l[i]); y=fi(r[i]); if(x==y) return 1; if(s[i]=='>') { add(x,y); du[y]++; } else if(s[i]=='<') { add(y,x); du[x]++; } } return 0; } int main() { int i,j,k,ans; while(~scanf("%d %d",&n,&m)) { ans=Map(); if(ans) { printf("CONFLICT\n");continue; } ans=topo(); if(!ans) puts("OK"); else if(ans == 1) puts("CONFLICT"); else puts("UNCERTAIN"); } return 0; }