CF1559 D2. Mocha and Diana (Hard Version)

这场区分度比较低完全就是手速场嘛...趁机上了波分。
感觉这场最有思维量的就是这道D2了(D1直接n2并查集水过去了)
从D1我们就有一种感觉,题目给我们的其实是两个森林,我们每次肯定是将森林中的两棵树连接在一起。
那么我们不妨设置1号节点所在的树为主树,让森林中其他树都尽可能连接到主树上去。
所以我们先按原图读进来,之后用并查集处理一开始的连接情况,并且父节点都尽量取小(因为1为主树)
之后我们尝试将其他不在主树上的点都连一条1 - i的边,使其与主树相连。如果能成功添加也要算做答案。
之后我们发现有些点是填加不了的,比如这个点在第一张图里已经在主树中,但是第二张图这个点不在主树中。
于是我们开两个数组记录这些点,如果在一不在二就放入v2, 在二不在一就放入v1。
为什么需要记录这些点呢?因为最后的答案必然是v1, v2的组合。
v1:在第一张图中不在主树上,但是在第二张图中在主树上
v2:在第二张图中不再主树上,但是在第一张图中在主树上
那么v1, v2进行连边就一定能让v1, v2在两张图都在主树上。
连上v1, v2后有些点就会不是可以选择的点了,于是我们需要将其弹出。之后重复这个过程即为答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 10;
int n;
int a[maxn];
int fa[maxn];
int _find(int x) {
if (x == fa[x]) return x;
return fa[x] = _find(fa[x]);
}
void _merge(int u, int v) {
u = _find(u), v = _find(v);
if (u == v) return ;
if (u > v) swap(u, v);
fa[v] = u;
}
int main() {
int n, m1, m2;
scanf("%d%d%d", &n, &m1, &m2);
for (int i = 1; i <= 2*n; ++ i) {
fa[i] = i;
}
for (int i = 1; i <= m1; ++ i) {
int u, v; scanf("%d%d", &u, &v);
u = _find(u), v = _find(v);
_merge(u, v);
}
for (int i = 1; i <= m2; ++ i) {
int u, v; scanf("%d%d", &u, &v);
u += n, v += n;
u = _find(u), v = _find(v);
_merge(u, v);
}
stack<int> p1, p2;
vector<pair<int, int> > rec;
for (int i = 1; i <= 1; ++ i) {
for (int j = i+1; j <= n; ++ j) {
int u1 = _find(i), v1 = _find(j);
int u2 = _find(i+n), v2 = _find(j+n);
//cout << u1 << " " << v1 << " " << u2-n << " " << v2-n << endl;
if (v1 != 1 && v2 != 1+n) {
_merge(1, v1);
_merge(1+n, v2);
rec.push_back({1, j});
continue;
}
if (v1 != 1) p1.push(j);
if (v2 != 1+n) p2.push(j);
}
}
while (p1.size() && p2.size()) {
//cout << p1.top() << " " << p2.top() << endl;
if (_find(p1.top()) == 1 && _find(p1.top()+n) == 1+n) {
p1.pop();
continue;
}
if (_find(p2.top()) == 1 && _find(p2.top()+n) == 1+n) {
p2.pop();
continue;
}
rec.push_back({p1.top(), p2.top()});
_merge(p1.top(), p2.top());
_merge(p1.top()+n, p2.top()+n);
p1.pop();
p2.pop();
}
cout << rec.size() << endl;
for (auto i : rec) {
cout << i.first << " " << i.second << endl;
}
return 0;
}

浙公网安备 33010602011771号