题解:P16007 [CCO 2016 Day 1] Field Trip 郊游
闲话
传说 CSP 考前写题解 RP++?
这题放模拟赛 T1 被秒切了,然后卡了半天一直 RE 测不出来问题,后来发现是没开大栈空间。
好消息是 CSP 等一般都是无限栈空间或者是与题目内存限制等大的,反正几乎无需担心。
正文
不难将其抽象成一个图论结构。那么题目变为: 个点, 条双向边的图。你可以删去一些边。最终你需要最大化大小恰好为 的连通块数量,在此基础上最小化删的边数。
Hints
- 我们只能删边,而不能建立,这意味着什么?
- 由于每个点度数不超过 ,所以一整个连通块会是什么形状?
- 我们需要知道连通块的什么信息才能求答案?如何求得?
答案
- 这意味着如果 两点在最后是连通的,那么它们在最开始的图上也必然是连通的。也就是说,如果点 开始时不与 连通,那么最终也不可能与 连通。
- 我们画画图就可以发现连通块不是链就是环。
- 当然是需要知道连通块的大小,以及它是环还是链。
第一个结论很好想,我们删边是在破坏连通性,怎么可能越破坏越连通上了?
第二个结论的话自己画图理解:




首先链是一种树,一个点一进一出最多两个度,开头和末尾的点只有 个度,一共 个点 条边。我们将第一个点和最后一个点连起来(加到其它点上那它的度数就变成 了),此时每个点的度都恰好是 ,一共 个点 条边。如果我们继续加边就会发现加到哪儿都会是某个点度数为 不符合要求,因此确实只有这 种情况。
从这里我们也可以看出,因为环要多条边,我们(可能)还要删去,因此需要与链分开处理。
我们先看能选出来几个点。设某个连通块的大小为 。注意如果 那么根本不需要删边。
我们只能 个 个选,一共能选出 组,共 个,设 ,也就是不属于任何一组的点数。
接着我们看链的情况下要断几条边。首先,我们需要把 组当中组与组之间断开,一共断 条。
然后,如果 ,也就是还有剩余,那么还再断 条边要把这 个点和分好组的点断开,至于这 个点内部,因为肯定有 ,所以不用让他们不连通(因为无论如何都选不了),为了最小化断边数这 个点内部不用处理,一共断 条。
如果是环的话,同样分类讨论。如果 ,那么同样断开这 组,因为还要破环,所以是 ,刚好 条。如果 ,那和链的情况类似,还要再断一条。合计我们发现刚好断了 条边。
那么就算做完了,总结一下做法:
- 读入、建图。
- 遍历每一个点,如果它属于一个新连通块那就 DFS 求出连通块大小 ,否则的话之前一定被搜过了就跳过。
- 记录答案,选上点数 ,断掉边数分环和链分类讨论。
- 输出
最终时间复杂度是 DFS 的时间复杂度 、读入 条边复杂度 、遍历每个点的复杂度 ,合计时间复杂度还是 。
代码
#include <bits/stdc++.h>
#define FOR(i, j, k) for(ll i = j;i <= k;++i)
using namespace std;typedef long long ll
const ll N = 2e6 + 10;ll c, k, m, n, r, u, v, ans, cnt, sum;bool flg;vector<ll> g[N];bitset<N> vis;
void dfs(ll now, ll fa) { if(vis[now]) { // 回来了 flg = 1; // 那么就是环 return; // 不能再搜了,会走不出去的 } vis[now] = 1; // 标记访问过了 ++cnt; // 记录连通块大小 for(auto v:g[now]) { if(v == fa) continue; // 当然不能回去 dfs(v, now); }}
int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> k; FOR(i, 1, m) { cin >> u >> v; g[u].emplace_back(v), g[v].emplace_back(u); } FOR(i, 1, n) if(!vis[i]) { cnt = flg = 0; dfs(i, -1); if(cnt < k) continue; c = cnt / k, r = cnt % k; ans += c * k; // 先记录选了几个 if(cnt != k) { // 如果恰好 k 个那当然一条边都不用断 if(!flg) { if(!r) sum += c - 1; else sum += c; } else sum += ceil(1.0 * cnt / k); // 小心自动下取整! } } cout << ans << ' ' << sum; return 0;}理解万岁!RP++!
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!













