昨天挂了场比赛,发现好久没写并查集都生疏了,今天就又拿了道之前的老题目来做了下, 题目不难,要注意的地方都加了注释,如果有错误欢迎大牛指正
#include <iostream>
using namespace std;
const int size = 100100;
int root[size];
int find(int x)
{
int t = x;
while (t != root[t]){
t = root[t];
}
return t;
}
void unio(int x, int y)
{
int xx = find(x), yy = find(y);
if (xx == yy)return ;
if (yy > xx)root[yy] = xx;
else root[xx] = yy;
}
bool visited[100100];
int main()
{
bool flag = false;
while (!flag){
int a, b;
memset(visited, false, sizeof(visited));
int maxx = -1, minn = INT_MAX;
int jud = true;
int jud0 = true;
for (int i = 1; i < size; i ++)root[i] = i;
int nc = 0;
while (scanf("%d%d", &a, &b)){
if (a == 0 && b == 0){if (!nc)jud0=false;break;}
if (a == -1 && b == -1){flag = true; break;}
if (find(a) == find(b))jud = false;//如果之前存在a可抵达root[a]、存在b可抵达root[b]那么如果 find(a) == find(b)在归并之前就相等,则必存在另外一条路径可由a->b->root[a](或root[b])
else//如果有上述情况出现则可直接判断"No"
unio(a, b);
if (maxx < a)maxx = a;
if (maxx < b)maxx = b;
if (minn > a)minn = a;
if (minn > b)minn = b;
visited[a] = visited[b] = true;
nc ++;
}
if (!jud0){printf("Yes\n");continue;}//这个地方不知道为什么第一次输入0 0(地图不存在)要判断Yes,不知道是不是数据问题
if (flag)break;
for (int i = minn; i <= maxx ; i ++){
root[i] = find(i);
}
int k = 0;
for (int i = minn; i <= maxx; i ++){
if (root[i] == i && visited[i]){//这里判断是不是存在不连通的子图
k ++;
}
}
if (k != 1)jud = false;
jud?printf("Yes\n"):printf("No\n");
}
return 0;
}