题目大意:有n个点(编号0~n-1),有m个关系,“>”、“<”或者“=”。若这n个点能形成固定的链式大小关系,就输出”OK”,如果关系有冲突,则输出”CONFLICT”,如果关系不全,则输出”UNCERTAIN”。PS:坑点,”CONFLICT”优先于”UNCERTAIN”,所以判断到”UNCERTAIN”条件时,别急着输出”UNCERTAIN”,而是置一个”UNCERTAIN”的flag,等到最后先判断”CONFLICT”的条件,再判断”UNCERTAIN”的条件。
将有“=”关系的点merge在一起,作为一个点,然后进行拓扑排序
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 10010;
const int maxm = 20010;
int head[maxn];
int to[maxm], nxt[maxm], tot;
int fa[maxn], in[maxm];
bool vis[maxn];
int n, m;
int findfa(int x)
{
return x==fa[x]?x:fa[x]=findfa(fa[x]);
}
void merge_(int u, int v)
{
int f1 = findfa(u);
int f2 = findfa(v);
if(f1 != f2) fa[f2] = f1;
}
void addedge(int u, int v)
{
++tot;
to[tot] = v;
nxt[tot] = head[u];
head[u] = tot;
++in[v];
}
int topo_solve(int sum)
{
queue <int> q;
for(int i = 0; i < n; ++i)
{
int f = findfa(i);
if(!in[f] && fa[f]==i) q.push(f);
}
bool flag = 0;
while(!q.empty())
{
int tmp = q.front();
q.pop();
--sum;
if(!q.empty()) flag = 1;//优先判断冲突!!!
for(int i = head[tmp]; ~i; i = nxt[i])
{
--in[to[i]];
if(!in[to[i]]) q.push(to[i]);
}
}
if(sum > 0) return 0;
if(flag) return 2;
return 1;
}
int main()
{
while(~scanf("%d %d", &n, &m))
{
for(int i = 0; i <= n; ++i)
{
fa[i] = i;
head[i] = -1;
in[i] = 0;
}
tot = 0;
int sum = n;
int u[maxm], v[maxm];
char ch[maxm];
for(int i = 0; i < m ; ++i)
{
scanf("%d %c %d", &u[i], &ch[i], &v[i]);
if(ch[i]=='=')
{
--sum;
merge_(u[i], v[i]);
}
}
bool flag = 0;
for(int i = 0; i < m; ++i)
{
if(ch[i]=='=') continue;
int f1 = findfa(u[i]);
int f2 = findfa(v[i]);
if(f1 == f2)
{
flag = 1;
printf("CONFLICT\n");
break;
}
if(ch[i]=='<') addedge(f2, f1);
else addedge(f1, f2);
}
if(flag) continue;
int tag = topo_solve(sum);
if(!tag) printf("CONFLICT\n");
else if(tag==1) printf("OK\n");
else printf("UNCERTAIN\n");
}
return 0;
}