P3629 [APIO2010] 巡邏

yabnto發表於2024-06-12

思路

考慮 \(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;
}

相關文章