HDU 1811

时间:2023-11-24 15:32:56

http://acm.hdu.edu.cn/showproblem.php?pid=1811

中文码题

对于等号的情况,用并查集合并(因为编号不同一定可以分出先后)

然后判断能否构成拓扑排序,以及拓扑排序是不是唯一的

题不难,考验代码能力,能1A证明手感还不错

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <set> using namespace std; int vis[],head[],cnt,fa[],st[]; struct p{
int a,b;
char op[];
}kk[]; struct node{
int s,t,nxt;
}e[]; void add(int s,int t){
e[cnt].s=s;e[cnt].t=t;e[cnt].nxt=head[s];head[s]=cnt++;
} void INIT(){
cnt=;
memset(head,-,sizeof(head));
} int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
} int dfs(int u){
vis[u]=-;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].t;
if(vis[v]<)return ;
else if(!vis[v] && !dfs(v))return ;
}
vis[u]=;
return ;
} int OK(int n){
for(int i=;i<n;i++){
if(!vis[i] && !st[i] && !dfs(i))return ;
}
return ;
} int IN[]; int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
INIT();
for(int i=;i<n;i++)fa[i]=i;
memset(IN,,sizeof(IN));
memset(st,,sizeof(st));
int flag=;
for(int i=;i<m;i++){
scanf("%d%s%d",&kk[i].a,kk[i].op,&kk[i].b);
if(kk[i].op[]=='='){
int pa=find(kk[i].a);
int pb=find(kk[i].b);
if(pa!=pb){
fa[pa]=pb;
st[pa]=;
}
}
else{
int pa=find(kk[i].a);
int pb=find(kk[i].b);
if(pa==pb)flag=;
}
}
if(!flag)puts("CONFLICT");//所给信息矛盾
else{
for(int i=;i<m;i++){
if(kk[i].op[]=='>'){
add(find(kk[i].a),find(kk[i].b));
IN[find(kk[i].b)]++;
}
else if(kk[i].op[]=='<'){
add(find(kk[i].b),find(kk[i].a));
IN[find(kk[i].a)]++;
}
}
memset(vis,,sizeof(vis));
if(!OK(n))puts("CONFLICT");//有环
else{
queue <int> q;
for(int i=;i<n;i++){
if(!st[i] && !IN[i])
q.push(i);
}
int flag=;
while(!q.empty()){
if(q.size()>){
flag=;
break;
}
int u=q.front();
q.pop();
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].t;
IN[v]--;
if(!IN[v])q.push(v);
}
}
if(!flag)puts("UNCERTAIN");//拓扑结构一层多于一个点,有多种情况
else puts("OK");
}
}
}
return ;
}