题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=1811
题意
有个rating系统,每个人的rating有高有低,给定n个人之间m条高低或等于关系。
判断:
1.是否能确定每个人之间的高低情况
2.是否有冲突
3.高低情况不确定
注意:如果信息中同时包含冲突且信息不完全,也算冲突
思路
并查集缩点,将分数相同的缩点。拓扑排序即可,如果某次出现两个或两个以上的入度为0的点,则不能确定。如果出现环了,即是冲突。
#include<cstdio>
#include<queue>
#include<iostream>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<set>
#include<stack>
#include<algorithm>
#define cle(a) memset(a,0,sizeof(a))
#define inf(a) memset(a,0x3f,sizeof(a))
#define ll long long
#define Rep(i,a,n) for(int i=a;i<=n;i++)
using namespace std;
#define INF2 9223372036854775807ll
const int INF = ( 2e9 ) + 2;
const ll maxn = 10010;
int f[maxn];
int In[maxn];
vector<int> g[maxn];
struct edge
{
int u,v;
};
vector<edge> e;
int Find(int x)
{
return f[x]==x?x:f[x]=Find(f[x]);
}
void Union(int x,int y)
{
int xx=Find(x);
int yy=Find(y);
if(xx!=yy)
f[xx]=yy;
}
int topsort(int n)
{
int cnt=0,tot=0,unc=0;
int vis[maxn];
priority_queue<int> q;
memset(vis,0,sizeof(vis));
for(int i=0; i<n; i++)if(f[i]==i)tot++;
for(int i=0; i<n; i++)
if(In[Find(i)]==0&&!vis[Find(i)])
{
vis[Find(i)]=1;
q.push(Find(i));
cnt++;
}
if(cnt>=2)
unc = 1;
cnt=0;
while(!q.empty())
{
int u=q.top();
q.pop();
int f=0;
for(int i=0,L=g[u].size(); i<L; i++)
{
int v=g[u][i];
In[v]--;
if(In[v]==0)
{
q.push(v);
f++;
}
}
if(f>=2)unc=1;
cnt++;
}
if(cnt==tot)
{
if(unc)return 1;
else return 2;
}
else return 3;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
memset(In,0,sizeof(In));
for(int i=0;i<=n;i++)g[i].clear();
for(int i=0;i<=n;i++)f[i]=i;
e.clear();
for(int i=0; i<m; i++)
{
int u,v;
char op;
scanf("%d %c %d",&u,&op,&v);
if(op=='=')
Union(u,v);
else if(op=='>')
e.push_back(edge{u,v});
else
e.push_back(edge{v,u});
}
for(int i=0,L=e.size();i<L;i++)
{
int u=e[i].u,v=e[i].v;
g[Find(u)].push_back(Find(v));
In[Find(v)]++;
}
int flag=topsort(n);
if(flag==1)
printf("UNCERTAIN\n");
else if(flag==2)
printf("OK\n");
else
printf("CONFLICT\n");
}
}