题目链接-HDU1811
开始是在并查集专题看到的这道题,然后就往并查集方向想,考虑了各种加点都没有办法解决问题,
后面看题解发现这道题的主体应该是拓扑排序,并查集仅仅是用来帮助解决“=”这个符号,进行删点处理的
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <vector>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
const int inf=0x7fffffff;
const int mod=1e9+7;
const int HASH=131;
int root[maxn];
int Find(int x)
{
return root[x]==x?x:root[x]=Find(root[x]);//并查集
}
int a[maxn];
int b[maxn];
char sign[maxn];
int degree_in[maxn];
vector<int> v[10050];//记录链接点
void init(int n)//初始化
{
for(int i=0;i<n;i++)
{
root[i]=i;
v[i].clear();
degree_in[i]=0;
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int sum=n;//记录拓扑排序未遍历点数
init(n);
for(int i=0;i<n;i++)
{
root[i]=i;
}
for(int i=0;i<m;i++)
{
scanf("%d %c %d",&a[i],&sign[i],&b[i]);//对初始数据进行存储
if(sign[i]=='=')
{
if(Find(a[i])!=Find(b[i]))
{
root[Find(a[i])]=Find(b[i]);//并查集的合并
sum--;//因为删去了一个点,需要遍历的点-1
}
}
}
for(int i=0;i<m;i++)
{
int x=Find(a[i]);
int y=Find(b[i]);
if(sign[i]=='>')
{
v[x].push_back(y);
degree_in[y]++;
}
else if(sign[i]=='<')
{
v[y].push_back(x);
degree_in[x]++;
}
}
queue<int> q;
for(int i=0;i<n;i++)
{
if(degree_in[i]==0&&Find(i)==i)
q.push(i);
}
int unknow=0;
while(!q.empty())
{
int tmp=q.front();
q.pop();
if(!q.empty()) unknow=1;
int len=v[tmp].size();
sum--;
for(int i=0;i<len;i++)
{
degree_in[v[tmp][i]]--;
if(!degree_in[v[tmp][i]]) q.push(v[tmp][i]);
}
}
if(sum) cout<<"CONFLICT"<<endl;
else if(unknow) cout<<"UNCERTAIN"<<endl;
else cout<<"OK"<<endl;
}
return 0;
}