hdu 小希的迷宫

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272

      这是一个并查集题,看似很水,其实陷阱也有很多,尤其是有了垃圾数据0 0,- -

      注意几个地方:(1)0 0输出Yes;(2),可能不是连通图,所以要判断是否连通,不连通No;(3),可能不是每个点都出现,比如最大点4,只出现了1 2 4,所以要注意标记。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <iostream>

using namespace std;

#define N 100005
int p[N], r[N], v[N];
bool ans[N];

void makeset(int n){
    for (int i = 1; i <= n; i++){
        p[i] = i;
        r[i] = 0;
        ans[i] = false;
    }
}
int findset(int x){
	if (x != p[x])
		p[x] = findset(p[x]);
	return p[x];
}
void unionset(int x , int y){
	x = findset(x);
	y = findset(y);
	if (r[x] > r[y])p[y] = x;
	else {
		p[x] = y;
		if (r[x] == r[y])r[y]++;
	}
}

int main()
{
    int a, b;
    while (scanf("%d%d", &a, &b) != EOF)
    {
        if (a == -1 && b == -1)break;
        
        //有垃圾数据0 0
        if (!a && !b){
            cout<<"Yes"<<endl;
            continue;
        }
        
        makeset(N - 3);
        int m = max(a, b);

        bool flag = false;

        unionset(a, b);
        //标记已经出现
        ans[a] = ans[b] = true;

        while (scanf("%d%d", &a, &b) && (a || b))
        {
            //判断是否有环
            if (findset(a) == findset(b))
                flag = true;
            else {
                unionset(a, b);
            }
            m = max(m, max(a, b));
            ans[a] = ans[b] = true;
        }
    
        //判断根节点是否唯一
        int temp = -1;
        for (int i = 1; i <= m; i++){
            if (ans[i]){
                if (temp == -1)temp = findset(i);
                else if (temp != findset(i))
                {
                    flag = true;
                    break;
                }
            }
        }

        if (flag)cout<<"No"<<endl;
        else cout<<"Yes"<<endl;
    }
    return 0;
}


posted @ 2011-06-26 10:46  like@neu  阅读(261)  评论(0编辑  收藏  举报