Codeforces Round 998 (Div. 3) E【dfs + 根节点储存】实现的类似并查集的功能

目录

1.概论

2.dfs + 根节点模拟

3.题目含义

4.具体操作

5.代码

6.题目


1.概论

        并查集是一种树形数据结构,主要实现并和查的功能。即合并两个集合或者查找某个元素在哪个集合中。

2.dfs + 根节点模拟

        dfs可以帮助我们遍历一棵树,而我们可以通过储存根节点的方式,在遍历过程中给该树中所有的子节点分发该子节点的最大上司(根节点)。从而在访问到每个节点时,就可以通过该节点储存的最大上司,知道该节点在哪个树中。

3.题目含义

        题目要求在G中,如果两点之间有路径相连则F中也一定要有,如果G中两点没有路径,但是F中有,则要删除F中的一条边。如果在 G 中两点有路径但是 F 中没有则需要添加一条边。

4.具体操作

        根据树的性质,如果两个点在一个树里,则两个点之间一定存在一个连通路径可以抵达。所以我们将问题转换为判断每个点是否与树根连通,如果同样的一个点在F和G中连着不同的树根就是我们要处理的是另外两种情况。

        第一种是在 G 中两点没有连通,但是在 F 中有连通,对应了代码是:

if (gc[now] != c)

        第二种是在 G 中两点连通,但是在 F 中两点没有连通,对应了代码是:

if (gcol[i] != i + 1) ans++;

5.代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void gfs(int u, int c, vector<vector<int>> &gl, vector<int> &gc) {
	gc[u] = c;
	for (int now : gl[u]) {
		if (gc[now] == 0) {
			gfs(now, c, gl, gc);
		}
	}
}

int ffs(int u, int c, vector<vector<int>> &fl, vector<int> &gc, vector<int> &fc) {
	int res = 0;
	fc[u] = c;
	for (int now : fl[u]) {
		if (fc[now] == 0) {
			if (gc[now] != c) {
				res++;//在 F 中该边连接了和 G 不同的根节点,则删除该边。
			}
			else res += ffs(now, c, fl, gc, fc);
		}
	}
	
	return res;
}

void com_list(int m, vector<vector<int>> &sl) {
	for (int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		sl[--u].emplace_back(--v);
		sl[v].emplace_back(u);
	}
}

void solve() {
	int n, m1, m2;
	cin >> n >> m1 >> m2;
	vector<vector<int>> fline(n);
	vector<vector<int>> gline(n);
	com_list(m1, fline);
	com_list(m2, gline);

	vector<int> fcol(n);
	vector<int> gcol(n);
	int ans = 0;
	for (int i = 0; i < n; i++) {
		if (gcol[i] == 0) {
			gfs(i, i + 1, gline, gcol);
		}
		if (fcol[i] == 0) {//表示i当前是F中一个树的根节点
			ans += ffs(i, gcol[i], fline, gcol, fcol);
			if (gcol[i] != i + 1) ans++;//G 中该点对应的树根与F中的点对应的树根不一样
		}
	}

	cout << ans << endl;
}

signed main() {
	int t;
	cin >> t;
	while (t--) {
		solve();
	}
}


6.题目

https://codeforces.com/problemset/problem/2060/E

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值