算法训练1-day46-图论

20 阅读2分钟
  1. 107. 寻找存在的路线 并查集实现;
  • 用一个数组记录每个节点所属集合的根父节点;
  • 每个节点的父节点初始化为自己;
  • 查找父节点时,递归查找,直到找到节点本身就是自己的父节点,代表它就是所属集合的根父节点;否则,继续找当前节点父节点的父节点;注意这里可以同时将当前节点的父节点设置为根父节点来压缩路径,因为我们只需要找到节点是否在同一个集合,不关心它们之间的路径,因此我们可以将集合中所有节点的父节点都指向根父节点,以此做到压缩路径来加快查询的效果
  • 将两个节点加入同一个集合时,先找他们的根父节点,如果两者的根父节点相同,那么不需要做任何操作;否则将一个节点的根父节点的父节点设置为另外一个节点的根父节点即可
  • 判断两个节点是否在同一集合,只需要判断它们的根父节点是否相同即可
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

class DisjointSet {
public:
  DisjointSet(int n) {
    father = vector<int>(n + 1);
    for (int i = 1; i <= n; i++) {
      father[i] = i; // 初始化每个节点的父节点为自己
    }
  }
  int find(int node) {
    if (node == father[node]) {
      return node; //是集合的根
    } else {
      father[node] = find(father[node]);
      return father[node];
    }
  }

  void join(int from, int to) {
    int fromFather = find(from);
    int toFather = find(to);
    if (fromFather == toFather)
      return;
    father[toFather] = fromFather;
  }

  bool isSameSet(int node1, int node2) {
    node1 = find(node1);
    node2 = find(node2);
    return node1 == node2;
  }

private:
  vector<int> father;
};

int main() {
  int n = 0, m = 0;
  cin >> n >> m;

  DisjointSet disjointSet(n);
  int from, to;
  for (int i = 0; i < m; ++i) {
    cin >> from >> to;
    disjointSet.join(from, to);
  }
  cin >> from >> to;
  cout << ((disjointSet.isSameSet(from, to)) ? 1 : 0) << endl;
  return 0;
}
```# 算法训练1-day45-图论