1.题目链接。题目大意其实很清楚了,就是给你一些点对,这些点对之间有边相连。这些边连起来组成了一个迷宫,现在的问题是从迷宫上的任意一个点到另外一个点要求只能有一条路径。判断给出的图是否是满足条件的。看到这个要求其实很简单了,就是图的生成树嘛,n个顶点需要n-1条边,至于无向图的联通判断我们采用并查集,因为如果一条边上的两个点具有相同的祖先,那么一定是有环存在的,所以我们对输入的每一条边进行并查操作,如果是有公共的祖先,那么不用再加入有一个联通分量,但是这是我们标志是否有环的那个flag要设置成true。如果没有,并到一起,并且边数加一。最后统计边数是否是点数减一即可。至于点数的计算,我们使用set,每次输入的两个点,insert进去。这样比较size和边数即可。代码实现如下:
#include<iostream>
#include<set>
#pragma warning(disable:4996)
using namespace std;
const int N = 1e5 + 10;
int pre[N];
int find(int a)
{
return a == pre[a] ? a : pre[a] = find(pre[a]);
}
void join(int a, int b)
{
int x = find(a);
int y = find(b);
if (x != y)
{
pre[x] = y;
}
}
int main()
{
int u, v;
while (~scanf("%d%d", &u, &v)&&u!=-1&&v!=-1)
{
for (int i = 0; i < N; i++)
pre[i] = i;
if (u == 0 && v == 0)
{
puts("Yes");
continue;
}
set<int>s;
int fx = find(u);
int fy = find(v);
pre[fx] = fy;
int cnt = 0;
int flag = 0;
s.insert(u);
s.insert(v);
cnt++;
while (scanf("%d%d", &u, &v))
{
if (!u && !v)break;
int x = find(u);
int y = find(v);
s.insert(u);
s.insert(v);
cnt++;
if (x != y)
{
pre[x] = y;
}
else
{
flag = 1;
}
}
if (flag || (cnt + 1) != s.size())
{
puts("No");
}
else
{
puts("Yes");
}
}
return 0;
}