这题有3个方面值得深思
1.=的处理,读入的时候就先考虑=的,用并查集合并,把第二个节点完全用第一个节点代替,后面建图的时候都使用的是并查集的根节点即可
2.判断是否是唯一确定的,就看队列中的size是否永远<=1,若出现>=2,则说明同时有两个点的入度为0,就不能唯一确定
3.判断是否有冲突,先记录并查集后,有多少个连通块,记为sum,然后再判断队列中一共运行了多少个点,记为cnt,若cnt等于sum,那么就没冲突,否则就有冲突,因为如果存在环,那么必然那整个环上的任意一点的入度都会大于0,所以,这个环的节点永远不会进入队列
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mod=142857;
const int MX=10000+5;
const int INF=0x3f3f3f3f;
int rear=0;
int vis[MX],IN[MX],P[MX];
vector<int>G[MX];
int find(int x){
return P[x]==x?x:(P[x]=find(P[x]));
}
void Union(int u,int v){
int p1=find(u),p2=find(v);
P[p1]=p2;
}
struct Edge{
int u,v;
}E[2*MX];
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
rear=0;
memset(IN,0,sizeof(IN));
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++){
G[i].clear();
P[i]=i;
}
for(int i=1;i<=m;i++){
int u,v;char op[10];
scanf("%d%s%d",&u,op,&v);
if(op[0]=='<'){
E[++rear].u=u;
E[rear].v=v;
}else if(op[0]=='>'){
E[++rear].u=v;
E[rear].v=u;
}else Union(u,v);
}
int sign=0;
for(int i=1;i<=rear;i++){
int p1=find(E[i].u),p2=find(E[i].v);
G[p1].push_back(p2);
IN[p2]++;
}
int cnt=0,sum=0;
for(int i=0;i<n;i++) vis[find(i)]=1;
for(int i=0;i<n;i++) sum+=vis[i];
queue<int>work;
for(int i=0;i<n;i++){
if(vis[i]&&!IN[i]){
work.push(i);
}
}
while(!work.empty()){
if(work.size()>=2) sign=2;
int u=work.front();
work.pop();
cnt++;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
IN[v]--;
if(!IN[v]) work.push(v);
}
}
if(cnt!=sum) sign=1;
printf("%s\n",sign==0?"OK":(sign==1?"CONFLICT":"UNCERTAIN"));
}
return 0;
}