hduoj1272:小希的迷宫

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

题目是判断给定的图是否存在环与孤立的点。使用并查集即可判断,如果存在环路,则必有一条边使得当这条边的两端的顶点的根节点属于同一个集合,因而在合并操作的时候判断这条边的两个节点的根节点是否属于同一个集合。孤立的点,则会出现,合并的最后仍至少有两个点的根节点为自身。poj的1308和此题类似

代码如下:

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

using namespace std;

const int maxn = 100005 ;

int parent[maxn] ;//记录每个节点的父节点
bool flag ;//标记是否存在环路
bool vis[maxn] ;//标记那些节点存在
//初始化,对并查集的第一个操作
void init()
{
	int i ;
	flag = 1 ;
	for(i = 1 ; i <= maxn ; i ++)
	{
		parent[i] = i ;
		vis[i] = 0 ;
	}

}
//查找节点x的根节点
int find_x(int x)
{
	int r = x ;

	while(r!=parent[r])
		r = parent[r] ;

	return r ;
}
//合并操作
void join(int x , int y)
{
	int p = find_x(x) ;
	int q = find_x(y) ;
	//判断根节点是否相同,如果相同,则表示则两个点已在同一个集合中,则此边的加入会形成环路
	if(p==q)
	{
		flag = false ;
		return ;
	}

	else
	{
		parent[p] = q ;
	}
	return ;
}
//查找是否有孤立点的存在
bool count(int x)
{
	int i ;
	int sum = 0 ;

	for(i = 1 ; i <= x ;i ++)
	{
		if(parent[i]==i && vis[i])
		{
			sum ++ ;
		}
		if(sum > 1)
		{
			return 0 ;
		}
	}
	return 1 ;

}

int main()
{
	int p ;
	int q ;
	int w ;//用于保存所有节点的最大编号,大于此编号的节点不用查找时访问

	//freopen("data.in" ,"r" , stdin) ;

	while(scanf("%d%d" , &p , &q)!=EOF)
	{
		init()   ;

		if(p==-1&& q==-1)
			break ;
		//注意如果直接为空
		if(p==0 && q== 0 )
		{
			printf("Yes\n") ;
			continue ;
		}

		else {

			join(p ,q) ;
			vis[p] = vis[q] = 1 ;
			w = q > p ? q : p ;

			while(scanf("%d%d" , &p ,&q)&&(p||q))
			{
				vis[p] = vis[q] = 1 ;

				if(p!=q)
					join(p ,q) ;
				if(w < p)
					w = p ;
				if(w < q)
					w = q ;
			}

			if(flag && count(w))
			{
				printf("Yes\n") ;
			}
			else
			{
				printf("No\n") ;
			}

		}
	}
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值