[补题记录] Atcoder Beginner Contest 304(E)

 URL:https://atcoder.jp/contests/abc304

目录

E

Problem/题意

Thought/思路

Code/代码


E

Problem/题意

给一个有自环、重边的无向图。给出 K 组点对,只要图 G 上没有这 K 组点对的通路,则称 G 为 Good。

现在问,若添加一条边,图 G 是否还是 Good。

Thought/思路

并查集。

我们首先把自环和重边忽略(反正是无向图),观察样例一,那么就会得到三个强连通分量:{1,2,3}、{4,5}、{6}。

因为题目说了,保证所给的图 G 一定是 Good,说明接下来的 K 个点对,一定不会在同一个强连通分量的内部产生;也就说明了,当新添加的边将两个不在同一个强连通分量的点连接起来时,这两个分量内的点就能互通,就很可能导致出现 K 组点对中的通路。

此时我们再观察样例一的输出,比如添加 2 - 5 这条边,就会将 {1,2,3}、{4,5} 连通,使得满足了 K 组点对中的某一个通路,则错误。

那么我们只需要记录所有的点属于哪一个集合,以及 K 组点对中的两个点 {Xi,Yi} 代表的集合 {Ai,Bi},就可以在添加边的时候,通过判断连接的两个点是否在 {Ai,Bi} 中,即可得到答案。

Code/代码

#include "bits/stdc++.h"

int n, m, k, q, fa[200007];

std::map <std::pair <int, int>, int> mp;

int find(int x) {
	return x == fa[x] ? fa[x] : fa[x] = find(fa[x]);
}

signed main() {
	std::cin >> n >> m;
	for (int i = 1; i <= n; ++ i) fa[i] = i;

	for (int i = 1; i <= m; ++ i) {
		int x, y; std::cin >> x >> y;
		fa[find(x)] = find(y);
	}

	std::cin >> k;
	for (int i = 1; i <= k; ++ i) {
		int x, y; std::cin >> x >> y;
		int a = find(x), b = find(y);
		if (a == b) continue; // 其实这个没必要,题目已经保证给的 G 是 good
		if (a > b) std::swap(a, b);
		mp[{a, b}] = 1;
	}

	std::cin >> q;
	for (int i = 1; i <= q; ++ i) {
		int x, y; std::cin >> x >> y;
		int a = find(x), b = find(y);
		if (a > b) std::swap(a, b);
		if (mp.count({a, b})) std::cout << "No\n";
		else std::cout << "Yes\n";
	}

}	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值