您的位置:首页 > 其它

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

2016-05-11 23:27 357 查看
解题思路:

拓扑排序的两个性质:

①如果一次入队入度为零的点大于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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图论