并查集:朴素算法 代码框架见下

#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;
}

代码练习 1 对应蓝桥云课 连通分量的个数

#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 ufs;
	cin >> n >> m;
	int count = n;
	ufs.Init(n);
	while (m--) {
		int a, b;
		cin >> a >> b;
		if (ufs.Union(a, b)) {
			count--;
		}
	}
	cout << count << endl;
	return 0;
}

代码练习 2 对应蓝桥云课 修建公路 代码见下

#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 ufs;
	cin >> n >> m;
	int count = n;
	ufs.Init(n);
	while (m--) {
		int a, b;
		cin >> a >> b;
		if (ufs.Union(a, b)) {
			count--;
		}
	}
	if(count <= 3){
    cout << 0 << endl;
  }else{
    cout << count - 3 << endl;
  }
	return 0;
}

代码练习3 对应蓝桥云课 修建公路1 代码见下

#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<long long> ks;
	cin >> n >> m;
	ks.Init(n);
	while (m--) {
		int a, b, c;
		cin >> a >> b >> c;
		ks.AddEdge(a, b, c);
	}
	cout << ks.Solve() << endl;
	return 0;
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐