您的位置:首页 > 其它

并查集+拓扑 hdu 1811 Rank of Tetris

2012-07-26 00:04 351 查看
hdu 1811 Rank of Tetris

//hdu 1811 Rank of Tetris
//并查集+拓扑

//思路:用并查集把相等的点归到一起,再用拓扑

//纠结这题纠结了一整天,看了n多的博客感觉这个不错
//http://972169909-qq-com.iteye.com/blog/1052820

#include <stdio.h>
#include <string.h>
#include <queue>

using namespace std;

#define comein freopen("in.txt", "r", stdin);
#define N 10005
#define M 20005
#define INF 1<<30
#define eps 1e-5

struct edge
{
int win, lost, next;
}adja[M];

int  tot;   //记录插入邻接表的个数
int degree
;
int win[M], lost[M], head
, set
;

int find(int root)
{
if(root == set[root])
return root;
return set[root] = find(set[root]);
}

void add_edge(int r_a, int r_b)
{
degree[r_b]++;
adja[++tot].win = r_a;
adja[tot].lost = r_b;
adja[tot].next = head[r_a];
head[r_a] = tot;
}

void topo(int n_node, int all)
{
queue<int>que;
bool uncer = false;
for(int i = 0; i < n_node; ++i)//要集合根节点且度为0的才可入队,若只判断
if(degree[i] == 0 && i == find(i))  //degree[find(i)]==0,可能会重复入队
que.push(i);
while(!que.empty())
{
if(que.size() > 1)
uncer = true;
int now = que.front();
que.pop();
all--;
for(int i = head[now]; i != -1; i = adja[i].next)
{
if(--degree[ adja[i].lost ] == 0)
que.push( adja[i].lost );
}
}
if(all > 0) //剩下的集合数大于1,则存在环
puts("CONFLICT");
else if(uncer == true)
puts("UNCERTAIN");
else
puts("OK");
}

int main()
{
// comein
int n_node, n_pair;
while(scanf("%d%d", &n_node, &n_pair) == 2)
{
for(int i = 0; i <= n_node; ++i)    //初始化并查集
set[i] = i;

int cnt = 0, all = n_node;    //若相等的点看做一个点,cnt记录总的点数

for(int i = 0; i < n_pair; ++i)
{
int wn, lt;
char ra;
scanf("%d %c %d", &wn, &ra, <);
if(ra == '=')
{   //这里要先求出来r_a和r_b,然后下面要用set[r_a] = r_b
//或set[r_b] = r_a,也不知道为什么,一天下来都在找bug
//无缘无故就被de掉了,提交了30几次,有的这里不用这样也可以ac
//有的不能,快崩溃了
int r_a = find(wn), r_b = find(lt);
if(r_a != r_b)
{
set[r_a] = r_b;
all--;
}
}
else if(ra == '>')
{
win[++cnt] = wn;
lost[cnt] = lt;
}
else
{
win[++cnt] = lt;
lost[cnt] = wn;
}
}

memset(adja, 0, (n_pair+5)*sizeof(edge));
for(int i = 0; i < n_node; ++i)
{
head[i] = -1;
degree[i] = 0;
}
tot = 0;
bool flag = false;
for(int i = 1; i <= cnt; ++i)
{
int r_a = find(win[i]), r_b = find(lost[i]);
if(r_a == r_b)  //上面的已经把'='的情况合并起来了
{           //这里都是处理不等的,如果出现相等的,说明冲突了
flag = true;
break;
}
add_edge(r_a, r_b);
}
if(flag == true)
{
puts("CONFLICT");
continue;
}
topo(n_node, all);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: