您的位置:首页 > 其它

HDU 1272 小希的迷宫(并查集)

2015-04-19 14:26 302 查看
题目大意:
题目说的是,给你一些边的关系来构成一棵树,然后让你求出这在这个生成树中是否有环,也就是说,对于树上的任意一个节点,是否存在从这个点到其余节点的第二条路径。

解题思路:
裸裸的并查集,我们只需要将每次输入的边的关系进行一个合并,然后用book[]数组去标记哪些点已经在这个生成树出现过了,因为我们知道在构树的过程中,我们预先并不能知道树上的节点编号是否连续,树上的节点编号的最大值和最小值分别为多少的问题。最后,扫一遍f[]数组,把f[i]==i并且book[i]==1的点有一个的话,那么我就出Yes。
还有一种情况就是说,我们再输入的过程中,如果发现了getf(a)==getf(b)的值,那么我们直接返回Yes了,因为这个时候就和最小生成树中的判断是否联通的问题很相似了。
代码:

# include<cstdio>
# include<iostream>
# include<cstring>

using namespace std;

# define MAX 100000+10

int f[MAX];
int book[MAX];

int getf ( int v )
{
if( f[v]==v )
{
return v;
}
else
{
f[v] = getf(f[v]);
return f[v];
}
}

void merge ( int v,int u )
{
int t1 = getf(v);
int t2 = getf(u);
if ( t1!=t2 )
{
f[t2] = t1;
}
}

int main(void)
{
int a,b;
while ( scanf("%d %d",&a,&b) )
{
//这仅仅是第一组数据
if ( a==-1&&b==-1 )
break;
if ( a==0&&b==0 )
{
printf("Yes\n");
continue;
}
memset(book,0,sizeof(book));
book[a] = book[b] = 1;
int _min, _max;
if ( a>b )
{
_min = b, _max = a;
}
else
{
_min = a, _max = b;
}

for ( int i = 1;i <= 100000;i++ )
{
f[i] = i;
}
int flag = 0;
merge(a,b);
while ( scanf("%d %d",&a,&b) )
{
if ( a==0&&b==0 )
break;
book[a] = book[b] = 1;
_max = max(_max,a);
_max = max(_max,b);
_min = min(_min,a);
_min = min(_min,b);
// cout<<_min<<" "<<_max<<" "<<endl;
if ( getf(a)==getf(b) )
{
flag = 1;
}
else
{
merge(a,b);
}

}
// printf("flag = %d\n",flag );

if ( flag )
{
printf("No\n");
continue;
}
/*  for ( int i = _min;i <= _max;i++ )
printf("%d ",f[i] );
cout<<endl;
for ( int i = _min;i <= _max;i++ )
printf("%d ",book[i]);
cout<<endl;
*/
for ( int i = _min;i <= _max;i++ )
{
if ( book[i]==1&&f[i]==i )
{
flag++;
}
}
// printf("flag = %d\n",flag );

if ( flag == 1 )
{
printf("Yes\n");
}
else
{
printf("No\n");
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: