题目大意:
让你输入n,m,代表一个迷宫中的两个点,要求这个迷宫中,不能有回路。这是一个无向图,但是其实根据题意来说,最终应该是一棵树。
解题思路:
只要输入的时候一开始判断两个点的父节点是不是相同的,如果相同,那么说明这两个点是连通的,你再加上去,就证明要产生回路啦。所以要排除,,还有,当输入n,m为0时,这时候输出yes,最后再判断下,这个图有没有连通分量就可以了。。。
#include
#include
using namespace std;
const int MAX=100005;
int pre[MAX];
int visited[MAX];
int find(int x)
{
int r, j;
r = x;
while(pre[r] != r)
{
r = pre[r];
}
while(pre[x] != r) //优化
{
j = pre[x];//从底部,一个一个判断上去,如果有一个父节点不是根节点,那么就将它放在根节点上
pre[x] = r;
x = j;
}
return r;
}
//int find(int x)
//{
//
// int r=x;
//
// while(pre[r]!=r)
//
// r=pre[r];
//
// return r;
//}
//void merge(int x,int y)
//{
//
// int fx,fy;
//
// fx=find(x);
//
// fy=find(y);
//
// if(fx!=fy)
//
// pre[fx]=fy;
//}
int main(void)
{
int n, m, f1, f2;
while(scanf("%d%d", &n,&m)==2)
{
memset(visited,0,sizeof(visited));
for(int i = 1; i < MAX; i++)
pre[i] = i;
if (n == -1 && m == -1 )
break;
if (n == 0 && m == 0 )
{
printf("Yes\n");
continue;
}
f1 = find(n);
f2 = find(m);
pre[f1]=f2;
visited[n]=visited[m]=1;
int minn=200005,maxn=0,flag=0;
if ( n< minn ) minn = n; //找到输入 的所有数据中最小的和最大的便于减小最后数组遍历时的复杂度
if ( m < minn ) minn = m;
if ( n> maxn ) maxn = n;
if ( m > maxn ) maxn = m;
while(scanf("%d%d", &n,&m))
{
if ( n== 0 && m == 0)
break;
if ( n< minn ) minn = n; //找到输入 的所有数据中最小的和最大的便于减小最后数组遍历时的复杂度
if ( m < minn ) minn = m;
if ( n> maxn ) maxn = n;
if ( m > maxn ) maxn = m;
visited[n]=visited[m]=1;
f1 = find(n);
f2 = find(m);
if(f1==f2)
{
flag=1;
}
else
{
pre[f1]=f2;
}
}
if(flag==1)
printf ("No\n");
if (flag==0)
{
for (int i = minn; i <= maxn; i++)
{
if ( visited[i] && pre[i] == i )
flag++;
}
if (flag == 1)
printf ("Yes\n");
else
printf ("No\n");
}
}
return 0;
}