HDU 1272 小希的迷宫 [并查集]

本文深入探讨了并查集算法的实现与应用,通过解决连通性问题,判断一组连通关系是否能构成一棵树。文章详细介绍了并查集的基本操作,包括查找、合并和判断两点是否在同一集合中。并通过具体代码示例展示了如何使用并查集解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#Description
给你若干个连通关系
如果最后全部连通,并且形成树,就输出Yes,否则输出No
#Algorithm
并查集
每次来两个点,先判断是否在同一个集合,如果在一个,那就已经连通了,直接NO
然后就并起来
接下来考虑虽然不成环,不过可能不是连通的
所有
par[i] = i 的点数就是连通块的数量,如果这个数比1大,那也输出NO
#Code

#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXL = 100000 + 9;
struct V
{
  V(){}
  V(int a, int b) : a(a), b(b) {};
  int a, b;
};
vector<V> v;
bool b[MAXL];
int l;
int par[MAXL];
int urank[MAXL];
void init()
{
  for (int i = 0; i < l; i++) {
    par[i] = i;
    urank[i] = i;
  }
}
int find(int x)
{
  if (par[x] == x) return x;
  else return par[x] = find(par[x]);
}
void unite(int x, int y)
{
  x = find(x);
  y = find(y);
  if (x == y) return;
  if (urank[x] < urank[y]) {
    par[x] = y;
  } else {
    par[y] = x;
    if (urank[x] == urank[y]) urank[x]++;
  }
}
bool same(int x, int y) {
  return find(x) == find(y);
}
void solve()
{
  memset(b, 0, sizeof(b));
  init();
  for (int i = 0; i < v.size(); i++) {
    if (!b[v[i].a]) {
      b[v[i].a] = true;
    }
    if (!b[v[i].b]) {
      b[v[i].b] = true;
    }
    if (same(v[i].a, v[i].b)) {
      puts("No");
      return;
    }
    unite(v[i].a, v[i].b);
  }
  int t = 0;
  for (int i = 0; i < l; i++) {
    if (b[i] && par[i] == i) t++;
    if (t == 2) {
      puts("No");
      return;
    }
  }
  puts("Yes");
}
int main()
{
 // freopen("in.txt", "r", stdin);
  l = 0;
  int a, b;
  for (;;) {
    scanf("%d%d", &a, &b);
    if (a == -1 && b == -1) break;
    if (a == 0 && b == 0) {
      solve();
      l = 0;
      v.clear();
      continue;
    }
    v.push_back(V(a - 1, b - 1));
    l = max(l, max(a, b));
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值