题目链接
思维的确是有点巧妙了,我们需要用到并查集和拓扑排序,一开始的时候,我看到这类题,会不自觉地和种类并查集联系起来,但是这道题又有不同的地方,它的种类个数不固定,所以说我们没法用种类并查集来思考,于是就想到建一个有向图,我们把相等的先处理掉,反正相等的不会影响到我们最后的排序,所以,相等的就直接用并查集连立放到同一棵并查集的树上去,然后我们对所有树的根进行大小的排列处理建立有向图,会发现建立的图可以用拓扑来一一排除做法,我们如果最后排不掉所有的点,就说明这里有环,而有环就说明有地方的大小错了,而如果有一次,我们有两个节点要同时处理,就是有时候queue<>中的存放的值>1就说明这两个节点没有相互间的关系,说明有不确定节点,而最后如果遍历完,就说明是OK的解。
我的做法或许会看上去有些繁琐(下面就是代码),因为我加了个map来去除重边的干扰(其实有没有都一样),只是为了queue<>的时候好处理些,然后我这里加边的方式是用的是链式前向星,所以会代码长度长些。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=10005;
int N, M, root[maxN], head[maxN<<2], cnt, point, degree[maxN];
bool flag;
map<pair<int, int>, bool> mp;
struct eddge
{
int no, to;
char state;
eddge(int a=0, int b=0, char c=NULL):no(a), to(b), state(c) {}
}ship[maxN<<1];
struct node
{
int nex, to, val;
node(int a=-1, int b=0, int c=0):nex(a), to(b), val(c) {}
}edge[maxN<<1];
void addEddge(int u, int v, int val)
{
edge[cnt]=node(head[u], v, val);
head[u]=cnt++;
}
queue<int> Q;
void init()
{
flag=false;
mp.clear();
while(!Q.empty()) Q.pop();
cnt=0; point=N;
memset(head, -1, sizeof(head));
memset(degree, 0, sizeof(degree));
for(int i=0; i<N; i++) { root[i]=i; }
}
int fid(int x) { return x==root[x]?x:(root[x]=fid(root[x])); }
void mix(int x, int y)
{
int u=fid(x), v=fid(y);
if(u!=v)
{
root[u] = v;
point--;
}
}
void bfs()
{
while(!Q.empty())
{
if(Q.size()>1) flag=true;
int now=Q.front(); Q.pop();
for(int u=head[now]; u!=-1; u=edge[u].nex)
{
int v=edge[u].to;
degree[v]--;
if(degree[v]==0)
{
Q.push(v);
point--;
}
}
}
}
int main()
{
while(scanf("%d%d", &N, &M)!=EOF)
{
init();
for(int i=1; i<=M; i++)
{
scanf("%d %c %d", &ship[i].no, &ship[i].state, &ship[i].to);
if(ship[i].state == '=')
{
mix(ship[i].no, ship[i].to);
}
}
for(int i=1; i<=M; i++)
{
if(ship[i].state == '=') continue;
if(ship[i].state == '<')
{
if(mp[make_pair(fid(ship[i].to), fid(ship[i].no))]) continue;
mp[make_pair(fid(ship[i].to), fid(ship[i].no))]=true;
addEddge(fid(ship[i].to), fid(ship[i].no), 1);
degree[fid(ship[i].no)]++;
}
else
{
if(mp[make_pair(fid(ship[i].no), fid(ship[i].to))]) continue;
mp[make_pair(fid(ship[i].no), fid(ship[i].to))]=true;
addEddge(fid(ship[i].no), fid(ship[i].to), 1);
degree[fid(ship[i].to)]++;
}
}
for(int i=0; i<N; i++)
{
if(degree[fid(i)]==0 && root[i]==i)
{
Q.push(fid(i));
point--;
}
}
bfs();
if(point>0) printf("CONFLICT\n");
else if(flag) printf("UNCERTAIN\n");
else printf("OK\n");
}
return 0;
}