思路:注意迷宫里元素的编号并不一定是连续的而且也不一定是从1开始,故在输入时用一个set保存元素编号,并查集时遍历set中元素,最终判断是不是只有一个集合即可(途中要判断是不是有多条路,具体见代码)。
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <deque>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>
#define debug(x) cout << "--------------> " << x << endl
using namespace std;
const double PI = acos(-1.0);
const double eps = 1e-10;
const long long INF = 0x7fffffff;
const long long MOD = 1000000007;
const int MAXN = 100000 + 7;
int pre[MAXN];
int u[MAXN], v[MAXN];
int findRootNode(int x)
{
int r = x;
while(pre[r] != r)
r = pre[r];
int i = x;
while(i != r)
{
int j = pre[i];
pre[i] = r;
i = j;
}
return r;
}
bool setMerge(int x, int y) //判断能否合并,并且合并
{
int root_x, root_y;
root_x = findRootNode(x);
root_y = findRootNode(y);
if(root_x < root_y)
pre[root_y] = root_x;
else
pre[root_x] = root_y;
return root_x == root_y;
}
int main()
{
int a, b;
int ans = 0;
int index = 0;
set<int> s; //保存输入的元素编号
bool flag = false;
for(int i = 0; i < MAXN; ++i)
pre[i] = i;
while(scanf("%d%d", &a, &b), a != -1 && b != -1)
{
if(a == 0 && b == 0)
{
for(int i = 0; i < index; ++i)
{
if(!setMerge(u[i], v[i])){} //不能合并,即v[i]、u[i]有相同祖先,不止一条条路
else
{
flag = true;
break;
}
}
if(flag)
printf("No\n");
else
{
for(set<int>::iterator it = s.begin(); it != s.end(); ++it) //对set中元素遍历
{
if(pre[*it] == *it)
{
ans++;
}
}
if(ans > 1)
printf("No\n");
else
printf("Yes\n");
}
for(int i = 1; i < MAXN; ++i)
pre[i] = i;
ans = 0;
flag = false;
index = 0;
s.clear();
}
else
{
u[index] = a;
v[index] = b;
index++;
s.insert(a);
s.insert(b);
}
}
return 0;
}