URL:https://atcoder.jp/contests/abc304
目录
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";
}
}