本题的主要问题就是给定m个名次大小关系,问每个人的名次是否能确定下来。
这个问题可以用topsort解决,名次发生冲突即找不到topsort结果。由于关系太少导致的名次不能确定直接在topsort过程中检测入度为0的点是否每次出现2个以上(即t-h>=2)那么说明拓扑排序结果不止一种,名次不能确定
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 11000;
const int M = 22000;
int poi;
int head[N];
struct Edge
{
int u,v,next;
}es[M];
int n,m;
int f[N];
int getf(int x){return f[x]==x? x:f[x]=getf(f[x]); }
void Merge(int a,int b)
{
int f1=getf(a),f2=getf(b);
if(f1==f2) return ;
f[f2]=f1;
poi--;
}
int q[N],h,t,cnt;
int in[N];
int a[N],b[N];
char s[N][5];
inline void add_edge(int u,int v)
{
es[++cnt].u=u;
es[cnt].v=v;
es[cnt].next=head[u];
head[u]=cnt;
}
bool vis[N];
void topsort()
{
h=t=0;
bool flagc=0,flagu=0;
for(int i=1;i<=cnt;i++)
{
int u=es[i].u;
int v=es[i].v;
if(u==v) flagc=1;
in[v]++;
}
for(int i=1;i<=n;i++)
{
int v;
if(vis[v=getf(i)]) continue;
if(in[v]==0) q[t++]=v,vis[v]=1;
}
if(t>1) flagu=1;
while(h<t)
{
int u=q[h++];
for(int i=head[u];~i;i=es[i].next)
{
int v=getf(es[i].v);
in[v]--;
if(in[v]==0) q[t++]=v;
}
if(t-h>1) flagu=1;
}
if(t<poi) flagc=1;
if(flagc) puts("CONFLICT");
else if(flagu) puts("UNCERTAIN");
else puts("OK");
}
void ini()
{
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) f[i]=i;
h=t=cnt=0;
memset(in,0,sizeof(in));
poi=n;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
ini();
for(int i=1;i<=m;i++)
{
scanf("%d%s%d",&a[i],s[i],&b[i]);
a[i]++,b[i]++;
if(s[i][0]=='=')
{
Merge(a[i],b[i]);
}
}
for(int i=1;i<=m;i++)
{
if(s[i][0]=='=')continue;
int u=getf(a[i]);
int v=getf(b[i]);
if(s[i][0]=='<') add_edge(u,v);
else add_edge(v,u);
}
topsort();
}
return 0;
}