hdu1811

/*
分析:
    拓扑排序+并查集。
    刚学拓扑排序时候没a掉的题,昨晚再次看到了,就又敲了一下,
不过敲之前想到的一个情况,在敲的过程中给忘掉了。。刚刚才想起
来。。。
    说一下大概思路吧,关键是怎么处理实力相同的点,既然是实力
相同,那么我的方法就是把两个点压缩为一个点(可以重新组合出一组
新的点,或者干脆就用并查集的思想来设置一个father,所有同一点
集的边都连到father上面)。
    然后就按照拓扑排序写就ok了。


                                                                2012-12-19
*/








#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
using namespace std;
#define N 10011
#define M 20011

int n,m;
int father[N],indegree[N],ans;
struct Eage{
	int from,to,next;
}eage[M];
int tot,head[N];
void add(int a,int b){
	eage[tot].from=a;eage[tot].to=b;eage[tot].next=head[a];head[a]=tot++;
}

int find(int k)
{
	if(father[k]==k)	return k;
	father[k]=find(father[k]);
	return father[k];
}
void get_map()
{
	int i;
	int a[M],b[M];
	char str[M][3];
	int f1,f2;
	for(i=0;i<n;i++)	father[i]=i;
	for(i=0;i<m;i++)
	{
		scanf("%d%s%d",&a[i],str[i],&b[i]);
		if(str[i][0]=='=')
		{
			f1=find(a[i]);
			f2=find(b[i]);
			father[f2]=f1;
		}
	}
	for(i=0;i<n;i++)	f1=find(i);					//如果想直接用某个点的father的话,这个不能漏掉。
	tot=0;
	memset(head,-1,sizeof(head));
	memset(indegree,0,sizeof(indegree));
	for(i=0;i<m;i++)
	{
		if(father[a[i]]==father[b[i]] && str[i][0]!='=')	{ans=1;break;}
		if(str[i][0]=='>')		{add(father[a[i]],father[b[i]]);indegree[father[b[i]]]++;}
		else if(str[i][0]=='<')	{add(father[b[i]],father[a[i]]);indegree[father[a[i]]]++;}
	}
}
int topsort()
{
	int tot2;
	int i,j,v,temp;
	int k,flag;
	queue<int>q;
	int now;

	tot2=flag=temp=0;
	for(i=0;i<n;i++)
	{
		if(father[i]==i)
		{
			tot2++;
			if(!indegree[i])	{temp++;q.push(i);}
			if(temp>1)	flag=2;
		}
	}

	k=0;
	while(!q.empty())
	{
		now=q.front();
		q.pop();
		k++;
		indegree[now]--;
		temp=0;
		for(j=head[now];j!=-1;j=eage[j].next)
		{
			v=eage[j].to;
			indegree[v]--;
			if(!indegree[v])	{temp++;q.push(v);}
		}
		if(temp>1)	flag=2;
	}
	if(k<tot2)	flag=1;
	return flag;
}
int main()
{
	while(scanf("%d%d",&n,&m)!=-1)
	{
		ans=0;
		get_map();
		if(!ans)		ans=topsort();
		if(!ans)		printf("OK\n");
		else if(ans==1)	printf("CONFLICT\n");
		else			printf("UNCERTAIN\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值