C++并查集
并查集:朴素算法 代码框架见下
#include<iostream>
#include<unordered_map>
using namespace std;//并:合并
//查:查找
//集:集合class UFSetsample {
public:void Init(int maxId);int Find(int id);bool Union(int id1, int id2);
private:unordered_map<int, int> m_set;
};void UFSetsample::Init(int maxId)
{m_set.clear();for (int i = 1; i <= maxId; ++i) {m_set[i] = i;}
}int UFSetsample::Find(int id)
{return m_set[id];
}bool UFSetsample::Union(int id1, int id2)
{int s1 = Find(id1), s2 = Find(id2);if (s1 == s2) {return false; // 合并失败}int n = m_set.size();for (int i = 1; i <= n; ++i) {if (m_set[i] == s1) {m_set[i] = s2;}}return true; // 合并成功
}int main() {int n, m;UFSetsample uf;cin >> n >> m;uf.Init(n);while (m--) {int a, b, c;cin >> a >> b >> c;if (a == 1) {uf.Union(b, c);}else {if (uf.Find(b) == uf.Find(c)) {cout << 'Y' << endl;}else {cout << 'N' << endl;}}}return 0;
}并查集:森林算法 代码框架见下
#include<iostream>
#include<unordered_map>
using namespace std;//并:合并
//查:查找
//集:集合class UFForest {
public:void Init(int maxId);int Find(int id);bool Union(int id1, int id2);
private:unordered_map<int, int> m_far; //m_far[x] 代表在这棵树上x的父节点编号
};void UFForest::Init(int maxId)
{m_far.clear();for (int i = 1; i <= maxId; ++i) {m_far[i] = i;}
}int UFForest::Find(int id)
{int p = m_far[id];while (p != m_far[p]) {p = m_far[p];}return p;
}bool UFForest::Union(int id1, int id2)
{int s1 = Find(id1), s2 = Find(id2);if (s1 == s2) {return false; // 合并失败}m_far[s1] = s2;return true; // 合并成功
}int main() {int n, m;UFForest uf;cin >> n >> m;uf.Init(n);while (m--) {int a, b, c;cin >> a >> b >> c;if (a == 1) {uf.Union(b, c);}else {if (uf.Find(b) == uf.Find(c)) {cout << 'Y' << endl;}else {cout << 'N' << endl;}}}return 0;
}C++ 并查集:启发式合并,代码框架见下
#include<iostream>
#include<unordered_map>
using namespace std;//并:合并
//查:查找
//集:集合class UFSetstar {
public:void Init(int maxId);int Find(int id);bool Union(int id1, int id2);
private:unordered_map<int, int> m_far; //m_far[x] 代表在这棵树上x的父节点编号unordered_map<int, int> m_height; //m_height[x] 代表x为根的这棵树的高度
};void UFSetstar::Init(int maxId)
{m_far.clear();m_height.clear();for (int i = 1; i <= maxId; ++i) {m_far[i] = i;m_height[i] = 1;}
}int UFSetstar::Find(int id)
{int p = m_far[id];while (p != m_far[p]) {p = m_far[p];}return p;
}bool UFSetstar::Union(int id1, int id2)
{int s1 = Find(id1), s2 = Find(id2);if (s1 == s2) {return false; // 合并失败}if (m_height[s1] < m_height[s2]) {m_far[s1] = s2;}else if (m_height[s2] < m_height[s1]) {m_far[s2] = s1;}else {m_far[s1] = s2;m_height[s2]++;}return true; // 合并成功
}int main() {int n, m;UFSetstar uf;cin >> n >> m;uf.Init(n);while (m--) {int a, b, c;cin >> a >> b >> c;if (a == 1) {uf.Union(b, c);}else {if (uf.Find(b) == uf.Find(c)) {cout << 'Y' << endl;}else {cout << 'N' << endl;}}}return 0;
}C++ 并查集:路径压缩 代码框架见下
#include<iostream>
#include<unordered_map>
using namespace std;//并:合并
//查:查找
//集:集合class UFSet {
public:void Init(int maxId);int Find(int id);bool Union(int id1, int id2);
private:unordered_map<int, int> m_far; //m_far[x] 代表在这棵树上x的父节点编号
};void UFSet::Init(int maxId)
{m_far.clear();for (int i = 1; i <= maxId; ++i) {m_far[i] = i;}
}int UFSet::Find(int id)
{if (m_far[id] == id) {return id;}m_far[id] = Find(m_far[id]);return m_far[id];
}bool UFSet::Union(int id1, int id2)
{int s1 = Find(id1), s2 = Find(id2);if (s1 == s2) {return false; // 合并失败}m_far[s1] = s2;return true; // 合并成功
}int main() {int n, m;UFSet uf;cin >> n >> m;uf.Init(n);while (m--) {int a, b, c;cin >> a >> b >> c;if (a == 1) {uf.Union(b, c);}else {if (uf.Find(b) == uf.Find(c)) {cout << 'Y' << endl;}else {cout << 'N' << endl;}}}return 0;
}C++ 并查集 Kruskal 代码框架见下
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>
using namespace std;//并:合并
//查:查找
//集:集合class UFSet {
public:void Init(int maxId);int Find(int id);bool Union(int id1, int id2);int Size() const;
private:unordered_map<int, int> m_far; //m_far[x] 代表在这棵树上x的父节点编号
};void UFSet::Init(int maxId)
{m_far.clear();for (int i = 1; i <= maxId; ++i) {m_far[i] = i;}
}int UFSet::Find(int id)
{if (m_far[id] == id) {return id;}m_far[id] = Find(m_far[id]);return m_far[id];
}bool UFSet::Union(int id1, int id2)
{int s1 = Find(id1), s2 = Find(id2);if (s1 == s2) {return false; // 合并失败}m_far[s1] = s2;return true; // 合并成功
}int UFSet::Size() const
{return m_far.size();
}template<typename T>
struct Edge {int u, v;T w;
};template<typename T>
class Kruskal {
public:void Init(int maxId);void AddEdge(int u, int v, T w);T Solve();
private:UFSet m_ufs;vector<Edge<T>> m_edges;
};template<typename T>
void Kruskal<T>::Init(int maxId)
{m_ufs.Init(maxId);m_edges.clear();
}template<typename T>
void Kruskal<T>::AddEdge(int u, int v, T w)
{m_edges.push_back({u, v, w});
}template<typename T>
bool cmp(const Edge<T>& a, const Edge<T>& b) {return a.w < b.w;
}template<typename T>
T Kruskal<T>::Solve()
{T sum = 0;int edgeCount = 0;sort(m_edges.begin(), m_edges.end(), cmp<T>);for (int i = 0; i < m_edges.size(); ++i) {Edge<T>& e = m_edges[i];if (m_ufs.Union(e.u, e.v)) {sum += e.w;++edgeCount;}}if (edgeCount < m_ufs.Size() - 1) {return -1;}return sum;
}int main() {int n, m;Kruskal<int> ks;cin >> n >> m;ks.Init(n);while (m--) {int a, b, c;cin >> a >> b >> c;ks.AddEdge(a, b, c);}int sum = ks.Solve();if (sum < 0) {cout << "orz" << endl;}else {cout << sum << endl;}return 0;
}