I will no longer be a trans|

yabnto

园龄:2年8个月粉丝:14关注:17

P3629 [APIO2010] 巡逻

思路

考虑 k=0 时,由于是树,根到每个点只有一条简单路径,所以每个边都会走两次即为 2(n2)

考虑 k=1 时,我们可以连一条边,使得成一个环,环上的边我们只用走一遍,所以我们希望环更可能大,所以将直径连边即可。

考虑 k=2 时,在 k=1 的基础上,同理我们需要去找已经连边后的直径然后连边,可是两个直径形成的环会有公共边,公共边又得重新走,出于贪心,我们将第一条直径的边权改为 1,这样最大的新直径在贪心下是正确的,处于计算,对于公共边我们在第一条直径减去了,在第二条直径加回来了,所以没变,还是走两次,也没问题,所以完结撒花。

思路出来了,我们来思考实现,出于偷懒,所以我们将两次直径都写成树形 dp(因为贪心无法解决负边权),由于我们需要将直径上边权改为 1,所以我们还得维护直径端点,那么我们可以利用 pairdp 数组,然后从最优的直径所在的拼成直径的顶点往两个端点跑,然后改边权即可,由于改边权是要改双向边,所以我们可以用网络流的见图方法,从而快速找到反向边,然后改边权。

code

#include <iostream>
#define h(x) g.h[x]
#define nxt(x) g.a[x].nxt
#define to(x) g.a[x].to
#define w(x) g.a[x].w
using namespace std;
using pii = pair<int, int>;
const int MaxN = 1e5 + 10;
struct Edge {
struct Node {
int to, w, nxt;
} a[MaxN << 1];
int h[MaxN], cnt;
Edge() {
cnt = 1;
fill(h, h + MaxN + 1, -1);
}
void insert(int x, int y) {
a[++cnt] = {y, 1, h[x]}, h[x] = cnt;
a[++cnt] = {x, 1, h[y]}, h[y] = cnt;
}
} g;
int n, k, s1, s2, res;
pii f[MaxN][2];
void DFS(int x, int fa, int &y) {
f[x][0] = f[x][1] = {0, x};
for (int i = h(x); ~i; i = nxt(i)) {
if (to(i) == fa) continue;
DFS(to(i), x, y);
pii t = f[to(i)][0];
t.first += w(i);
if (t >= f[x][0]) f[x][1] = f[x][0], f[x][0] = t;
else if (t > f[x][1]) f[x][1] = t;
}
if (f[y][0].first + f[y][1].first < f[x][0].first + f[x][1].first) y = x;
}
bool GO(int x, int fa, int y) {
if (y == x) return 1;
int res = 0;
for (int i = h(x); ~i; i = nxt(i)) {
if (to(i) == fa) continue;
if (GO(to(i), x, y)) res = 1, w(i) = w(i ^ 1) = -1;
}
return res;
}
int main() {
cin >> n >> k;
for (int i = 1, u, v; i < n; i++) {
cin >> u >> v, g.insert(u, v);
}
DFS(1, -1, s1), res = (f[s1][0].first + f[s1][1].first - 1);
if (k == 1) return cout << 2 * (n - 1) - res << endl, 0;
GO(s1, -1, f[s1][0].second), GO(s1, -1, f[s1][1].second);
DFS(1, -1, s2);
cout << 2 * (n - 1) - (f[s2][0].first + f[s2][1].first + res - 1) << endl;
return 0;
}

本文作者:yabnto

本文链接:https://www.cnblogs.com/ybtarr/p/18244871

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yabnto  阅读(4)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 光辉岁月 Audio artist
  3. 3 名前を呼ぶよ Audio artist
  4. 4 战歌 Audio artist
  5. 5 時を越えた想い Audio artist
  6. 6 所念皆星河 Audio artist
  7. 7 See you again Audio artist
所念皆星河 - Audio artist
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

Not available

点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起