SDUT 2798 小鑫的城堡
Time Limit: 1000MS Memory Limit: 65536KB
Problem Description
从前有一个国王,他叫小鑫。有一天,他想建一座城堡,于是,设计师给他设计了好多简易图纸,主要是房间的连通的图纸。小鑫希望任意两个房间有且仅有一条路径可以相通。小鑫现在把设计图给你,让你帮忙判断设计图是否符合他的想法。比如下面的例子,第一个是符合条件的,但是,第二个不符合,因为从5到4有两条路径(5-3-4和5-6-4)。
Input
多组输入,每组第一行包含一个整数m(m < 100000),接下来m行,每行两个整数,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。
Output
每组数据输出一行,如果该城堡符合小鑫的想法,那么输出”Yes”,否则输出”No”。
Example Input
5
2 5
2 3
1 3
3 6
4 6
6
1 2
1 3
3 4
3 5
5 6
6 4
Example Output
Yes
No
Hint
又是一道和SDUT 3386小雷的冰茶几http://blog.csdn.net/yxc9806/article/details/56035744 相似的题,比其多了判断有无回路
Submit
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000010;
int head[MAXN], t[MAXN];//head为房间的根,t有无房间
int Find(int x)//将路径都指向根
{
int r = x;
while(head[r] != r)
r = head[r];
int i = x;
while(head[i] != r)
{
int temp = head[i];
head[i] = r;
i = temp;
}
return r;
}
int Merge(int x, int y)//合并
{
int fx, fy;
fx = Find(x);
fy = Find(y);
if(fx != fy)
{
head[fy] = fx;
return 1;
}
return 0;
}
int main()
{
int i, M, x, y, road, flag;
while(~scanf("%d", &M))
{
memset(head, 0, sizeof(head));
memset(t, 0, sizeof(t));
for(i = 0; i < MAXN; i++)//初始化每个房间的根为自身
head[i] = i;
scanf("%d %d", &x, &y);
Merge(x, y);
t[x] = t[y] = 1;
road = 1;
flag = 1;
for(i = 1; i < M; i++)
{
scanf("%d %d", &x, &y);
if(t[x] == 0)//如果本来没有房间就创建房间,并多了一条边
{
road++;
t[x] = 1;
}
if(t[y] == 0)
{
road++;
t[y] = 1;
}
if(Merge(x, y))//一旦成功合并就少了一段边
road--;
else//x,y的根相同,有重复的边
flag = 0;
}
if(flag == 1 && road == 1)//未出现重复的边且剩余边数量为1(即都有同一个根)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}