专栏文章
题解:P11954 「ZHQOI R1」删边
P11954题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miptojp1
- 此快照首次捕获于
- 2025/12/03 17:46 3 个月前
- 此快照最后确认于
- 2025/12/03 17:46 3 个月前
分析
题目要求看起来很容易满足。
所以考虑直接求这个图的生成树,把生成树上的边删除,再删去一条两端没有叶子的边。
注意到无法删去边时生成树是菊花。此时只需将任意一条在生成树上(小心重边)的边放到生成树上,并将相邻的任意一条在生成树上的边删去即可。
Code
CPP#include <bits/stdc++.h>
using namespace std;
int u[500005], v[500005], vis[500005], fa[500005], d[500005];
set<pair<int, int> > p;
int find_fa(int x) {
return fa[x] ? (fa[x] = find_fa(fa[x])) : x;
}
void output(int m) {
int cnt = 0;
for (int i = 1; i <= m; i ++) {
if (!vis[i]) cnt ++;
}
cout << cnt << '\n';
for (int i = 1; i <= m; i ++) {
if (!vis[i]) cout << u[i] << ' ' << v[i] << '\n';
}
exit(0);
}
int main() {
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i ++) {
cin >> u[i] >> v[i];
}
for (int i = 1; i <= m; i ++) {
if (find_fa(u[i]) != find_fa(v[i])) {
fa[find_fa(u[i])] = find_fa(v[i]);
vis[i] = true;
d[u[i]] ++;
d[v[i]] ++;
}
}
for (int i = 1; i <= m; i ++) {
if (vis[i] && d[u[i]] > 1 && d[v[i]] > 1) {
vis[i] = false;
output(m);
}
}
for (int i = 1; i <= m; i ++) {
if (!vis[i] && !p.count(make_pair(min(u[i], v[i]), max(u[i], v[i])))) {
for (int j = 1; j <= m; j ++) {
if (vis[j] && (u[i] == u[j] || u[i] == v[j] || v[i] == u[j] || v[i] == v[j])) {
vis[j] = false;
vis[i] = true;
d[u[i]] ++;
d[v[i]] ++;
d[u[j]] --;
d[v[j]] --;
for (int i = 1; i <= m; i ++) {
if (vis[i] && d[u[i]] > 1 && d[v[i]] > 1) {
vis[i] = false;
output(m);
}
}
cout << "-1\n";
return 0;
}
}
assert(false);
}
p.insert(make_pair(min(u[i], v[i]), max(u[i], v[i])));
}
cout << "-1\n";
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...