P3629 [APIO2010] 巡逻

思路

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

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

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

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

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;
}
posted @ 2024-06-12 22:39  yabnto  阅读(2)  评论(0编辑  收藏  举报