hdu 1811(拓扑排序+并查集)

解题思路:

拓扑排序的两个性质:

①如果一次入队入度为零的点大于1则说明拓扑排序序列不唯一
②如果排序的总个数小于给定的个数,则说明存在回路
可以先把"="的两个数用并查集放在一个集合里,这样就只剩下">"和"<"了,可以用拓扑排序解决了。
不知道为什么TLE了。。待解决

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 10005;
int n,m,cnt,fa[maxn],in[maxn];
int que[maxn],head,tail;
vector<int> G[maxn];

void init()
{
	for(int i = 0; i <= n; i++)
		fa[i] = i;
	memset(in,0,sizeof(in));
	cnt = n;
	head = tail = 0;
}

int find(int x)
{
	if(fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}

void Union(int x,int y)
{
	int fx = find(x);
	int fy = find(y);
	if(fx != fy)
	{
		fa[fy] = fx;
		cnt--;
	}
}

int main()
{
	char str[2];
	int a,b;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		bool f1 = false,f2 = false;
		init();
		for(int i = 1; i <= n; i++)
		{
			scanf("%d %s %d",&a,str,&b);
			if(str[0] == '=')
				Union(a,b);
			else if(str[0] == '>')
			{
				int fa = find(a);
				int fb = find(b);
				if(fa == fb)
				{
					f1 = true;
					continue;
				}
				in[fb]++;
				G[fa].push_back(fb);
			}
			else
			{
				int fa = find(a);
				int fb = find(b);
				if(fa == fb)
				{
					f1 = true;
					continue;
				}
				in[fa]++;
				G[fb].push_back(fa);
			}
		}
		for(int i = 0; i < n; i++)
			if(in[i] == 0 && find(i) == i)
				que[tail++] = i;
		while(head < tail)
		{
			if(tail - head > 1) f2 = true;
			int t = que[head++];
			cnt--;
			for(int i = 0; i < G[t].size(); i++)
			{
				in[G[t][i]]--;
				if(in[G[t][i]] == 0)
					que[tail++] = G[t][i];
			}
		}
		if(cnt > 0 || f1 == true)
			printf("CONFLICT\n");
		else if(f2 == true)
			printf("UNCERTAIN\n");
		else printf("OK\n");
	}
	return 0;
}


你可能感兴趣的:(图论)