题目链接
思路:大于号和小于号处理就等价于方向路径,但是 ‘=’ 则要进行特殊处理,这里使用查并集的方法,对数据进行预处理,将所有相等的点收缩成一个点,再将新构成的点,进行拓扑排序,若是不能进行拓扑排序,那么直接输出“CONFLICT”,若是可以进行拓扑排序,但是有两个及以上的入度为0的点,则输出“UNCERTAIN ”,其余情况,输出“OK”;一些细节问题将在代码中进行陈述。
#include <iostream>
#include <queue>
#include <vector>
#include <string.h>
using namespace std;
int fnode[10005],n,fx,fy;
int in[10005];
vector <int> edge[10005];
void init(int n)
{
for(int i = 0; i < n; i++){
fnode[i] = i;
edge[i].clear();
in[i] = 0;
}
}
int search(int node)
{
while(node != fnode[node]){
node = fnode[node];
}
return node;
}
void toposort(int n,int res)
{
queue <int> q;
for(int i = 0; i < n; i++){
if(!in[i]&&search(i) == i){//避免将相等的数据图中的点误判进队列
q.push(i);
}
}
int flag = 0;
while(!q.empty()){
if(q.size() > 1)
flag = 1;
int p = q.front();
q.pop();
res--;
for(int i = 0; i < edge[p].size(); i++){
int y = edge[p][i];
in[y]--;
if(!in[y]){
q.push(y);
}
}
}
if(res)
cout<<"CONFLICT"<<endl;
else if(flag)
cout<<"UNCERTAIN"<<endl;
else
cout<<"OK"<<endl;
}
int main()
{
int n,m,res;
while(cin>>n>>m){
init(n);
res = n;//一定要设立一个代替n进行 -- 的变量,这样在被调函数中,不会出现漏掉大于减
int u[10005],v[10005];//完后将大于此时n的值的结点漏掉
char s[10005];
for(int i = 0; i < m; i++){//这里一定要是预处理,不能将两个循环合并
cin>>u[i]>>s[i]>>v[i];//万一出现先存入vector再合并点的情况,就会错误
if(s[i] == '='){
fx = search(u[i]);
fy = search(v[i]);
if(fx != fy){
fnode[fx] = fy;
res--;
}
}
}
for(int i = 0; i < m; i++){
if(s[i] == '>'){
fx = search(u[i]);
fy = search(v[i]);
edge[fx].push_back(fy);
in[fy]++;
}
if(s[i] == '<'){
fx = search(u[i]);
fy = search(v[i]);
edge[fy].push_back(fx);
in[fx]++;
}
}
toposort(n,res);
}
}