hdu 1811
题目
http://acm.hdu.edu.cn/showproblem.php?pid=1811
思路
http://www.cnblogs.com/-sunshine/archive/2012/07/28/2612669.html
这位同学的代码很有帮助。
注意:并入一个子集时sum要减,因为参加算法的节点减少了
判断冲突条件包括sum!=0。
注意数据有重边输入!
思路就是相等的进入一个集合,其余的拓扑排序
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
using namespace std;
//un判断有队列中有超过一个入度为0的节点,或是有环
//CON判断有xy父节点相同 但<或>就说明conflict
int pre[10010];
int rudu[10010];
int con,un;
int find(int x)
{
if(x!=pre[x])
pre[x]=find(pre[x]);
return pre[x];
}
void join(int x,int y)
{
int xx=find(x);
int yy=find(y);
if(xx!=yy)
pre[yy]=xx;
return;
}
typedef struct node
{
int to;
int next;
} node;
int head[10010];
node edges[20010];
int count;
void addnode(int from,int to,int k)
{
edges[k].to=to;
edges[k].next=head[from];
head[from]=k;
}
typedef struct jiedian
{
int a,b;
char ch;
} jiedian;
jiedian h[10010];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
un=0;
con=0;
count=0;
memset(pre,0,sizeof(pre));
memset(rudu,0,sizeof(rudu));
memset(head,-1,sizeof(head));
memset(edges,-1,sizeof(edges));
for(int i=0; i<n; i++)
{
pre[i]=i;
}
int sum=n;
for(int i=0; i<m; i++)
{
scanf("%d %c %d",&h[i].a,&h[i].ch,&h[i].b);
if(h[i].ch=='=')
{
if(find(h[i].a)!=find(h[i].b))
{
join(h[i].a,h[i].b);
sum--;
}
}
}
for(int i=0; i<m; i++)
{
if(h[i].ch=='=') continue;
int xx=find(h[i].a);
int yy=find(h[i].b);
if(xx==yy)
{
con=1;
break;
}
else
{
if(h[i].ch=='<')
{
addnode(yy,xx,++count);
rudu[xx]++;
}
else
{
addnode(xx,yy,++count);
rudu[yy]++;
}
}
}
queue<int> pq;
for(int i=0; i<n; i++)
{
if(i==pre[i]&&rudu[i]==0)
pq.push(i);
}
while(!pq.empty())
{
int t=pq.front();
pq.pop();
sum--;
if(!pq.empty())
un=1;
for(int i=head[t]; i!=-1; i=edges[i].next)
{
rudu[edges[i].to]--;
if(!rudu[edges[i].to])
pq.push(edges[i].to);
}
}
if(con==1||sum!=0)
printf("CONFLICT\n");
else if(un==1)
printf("UNCERTAIN\n");
else
printf("OK\n");
}
return 0;
}