题意:
(中文)
思路:
把所有得分相同的选手放到同一个集合里面,然后对这些结合的关系进行拓扑排序,看是否可以存在一个完全的有向无环图。
1.利用并查集合并集合。
2.利用队列进行拓扑排序,如果队列里面的元素个数超过1个了,那么就说明此时信息缺失(因为这些队列里面的参赛选手都没有比它们大的了,他们之间的相互关系无法确定),如果最后入队的个数小于集合的个数,说明在图中有环,就是冲突了(因为环里面没有任何一个点的入度为0)
Code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>
#define TEST
#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
#define See(a) cout << #a << " = " << a << endl;
#define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
#define debug(a, s, e) rep(_i, s, e) {cout << a[_i] << ' ';} cout << endl;
#define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee)}
#else
#define See(a)
#define See2(a, b)
#define debug(a, s, e)
#define debug2(a, s, e, ss, ee)
#endif // TEST
const int MAX = 2e9;
const int MIN = -2e9;
const double eps = 1e-8;
const double PI = acos(-1.0);
using namespace std;
const int N = 20000 + 5;
char op[N][2];
int a[N], b[N];
int uf[N], in[N];
vector<int> vec[N];
void init(int n)
{
for(int i = 0; i < n; ++i)
{
uf[i] = i;
vec[i].clear();
}
Mt(in, 0);
}
int fd(int n)
{
if(uf[n] != n)
{
uf[n] = fd(uf[n]);
}
return uf[n];
}
void unionSet(int a, int b)
{
int f1 = fd(a), f2 = fd(b);
if(f1 != f2)
uf[f1] = uf[f2];
}
int bfs(int n, int tem, bool &flag)
{
queue<int> Q;
for(int i = 0; i < n; ++i)
{
if(!in[i] && fd(i) == i)//选择所有入读为0的根(合法情况下只有一个)
{
Q.push(fd(i));
}
}
while(!Q.empty())
{
if(Q.size() > 1) flag = true;
int st = Q.front(); Q.pop();
tem--;
for(int i = 0; i < vec[st].size(); ++i)
{
const int &to = vec[st][i];
if(--in[to] == 0)//把通过此点连接的所有入读都减一,并找到这里面入度为0的点
{
Q.push(to);
}
}
}
return tem;
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
init(n);
int num = n;//最开始假设结合个数为n
for(int i = 0; i < m; ++i)
{
scanf("%d%s%d", &a[i], op[i], &b[i]);
if(op[i][0] == '=')
{
unionSet(a[i], b[i]);
num--;//合并集合时,集合个数减1
}
}
bool clash = false;
for(int i = 0; i < m; ++i)
{
if(op[i][0] == '=') continue;
int fa = fd(a[i]), fb = fd(b[i]);
if(fa == fb)//找到各自的集合,看是否是同一个集合里面的
{
clash = true;
break;
}
if(op[i][0] == '<')
{
vec[fa].push_back(fb);
in[fb]++;
}
else
{
vec[fb].push_back(fa);
in[fa]++;
}
}
if(clash)
{
printf("CONFLICT\n");
continue;
}
bool flag = false;
int tem = bfs(n, num, flag);//拓扑排序 flag记录是否是信息不全,返回还没有入队的集合个数
if(tem > 0)
{
printf("CONFLICT\n");
}
else if(flag)
{
printf("UNCERTAIN\n");
}
else
{
printf("OK\n");
}
}
return 0;
}