P4886 快递员

呃呃呃呃呃,兄弟们,终于AC快递员了,呃呃呃,这都什么日子啊,天天吃 18 发罚时。(来,兄弟们先吃)

思路

虽然有一堆点对,但是我们只用关注那些最长的点对即可,因为如果最长的点对已经不能放短了,那么你再怎么调其他的都改变不了现实,不过我们也要枚举每个点,所以时间还是很大,瓶颈在于会有很多不去要的冗余点,考虑直径最长,而直径上最为标志,最为好算的点就是重心,所以我们考虑每次跳重心,然后暴力算,那么一切将会分为一下几种情况:

  1. 当前最大的存在一条过重心,那么怎么动都会变得更大,直接输出
  2. 当前最大的边分布在了不同的重心的儿子子树中,那么同理动一次总有链被增加,所以也可以直接输出
  3. 以上都不满足,往最大边分布的儿子子树找重心然后跳即可

思路很简单,不过细节有点多

#include <iostream>
#include <vector>

using namespace std;

const int MaxN = 2e5 + 10, MaxK = 19;

struct S {
  int v, w;
};

int dis[MaxN], sz[MaxN], bsz[MaxN], gt[MaxN], que[MaxN], a[MaxN], b[MaxN], qtg, root, ans = 1e9, tot, n, tn, m;
vector<S> g[MaxN];
bool vis[MaxN];

void find(int x, int fa) {
  sz[x] = 1, bsz[x] = 0;
  for (auto i : g[x]) {
    if (vis[i.v] || i.v == fa) continue;
    find(i.v, x);
    sz[x] += sz[i.v];
    bsz[x] = max(bsz[x], sz[i.v]);
  }
  bsz[x] = max(bsz[x], n - sz[x]);
  if (bsz[x] < bsz[root]) {
    root = x;
  }
}

void GOGOGO(int x, int rt, int fa = -1) {
  gt[x] = rt;
  for (auto i : g[x]) {
    if (i.v == fa) continue;
    dis[i.v] = dis[x] + i.w;
    GOGOGO(i.v, rt, x);
  }
}

void DFS(int x) {
  if (vis[x]) {
    cout << ans << endl;
    exit(0);
  }
  vis[x] = 1, dis[x] = 0;
  for (auto i : g[x]) {
    dis[i.v] = i.w, GOGOGO(i.v, i.v, x);
  }
  int mxl = 0;
  for (int i = 1, tmp; i <= m; i++) {
    tmp = dis[a[i]] + dis[b[i]];
    if (mxl == tmp) que[++qtg] = i;
    if (mxl < tmp) {
      mxl = tmp, que[(qtg = 1)] = i;
    }
  }
  ans = min(ans, mxl);
  int lst = 0;
  for (int j = 1, tmp; j <= qtg; j++) {
    int i = que[j];
    if (gt[a[i]] != gt[b[i]]) {
      cout << ans << endl;
      exit(0);
    }
    if (!lst) lst = gt[a[i]];
    if (lst != gt[a[i]]) {
      cout << ans << endl;
      exit(0);
    }
  }
  root = 0, n = sz[lst], find(lst, 0), DFS(root);
}

signed main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> m, tn = n;
  for (int i = 1, u, v, w; i < n; i++) {
    cin >> u >> v >> w;
    g[u].push_back({v, w});
    g[v].push_back({u, w});
  }
  for (int i = 1; i <= m; i++) {
    cin >> a[i] >> b[i];
  }
  root = 0, bsz[0] = 1e9, find(1, 0), DFS(root);
  cout << ans << endl;
  return 0;
}
posted @ 2024-09-08 17:22  yabnto  阅读(2)  评论(0编辑  收藏  举报