Centipede Graph

Centipede Graph

对于非根节点 \(u\),设 \(son\) 为子节点数量,\(mx\) 和 \(nmx\) 分别为子节点 \(dp\) 值的最大值和次大值。

非根节点 \(u\) 的处理

情况一:\(son = 1\)

此时 \(deg[u] = son + 1 = 2\),\(u\) 只能作为长度为 \(1\) 的蜈蚣图中心。

\[ans = \max(ans, 1) \]

\(dp[u]\) 保持为 \(0\)。

情况二:\(son = 2\)

此时 \(deg[u] = 3\),\(u\) 只能作为端点。

如果 \(u\) 作为整条路径的最高点,则路径为 \(u\) 加上向下最长的一条子树链:

\[ans = \max(ans, mx + 1) \]

如果父边连上来,\(u\) 作为端点,路径到 \(u\) 结束,不能再向下延伸,所以:

\[dp[u] = 1 \]

情况三:\(son \ge 3\)

此时 \(deg[u] \ge 4\),\(u\) 可以作为中间节点。

如果 \(u\) 作为整条路径的最高点,则取两条最长的子树链加上 \(u\) 自身:

\[ans = \max(ans, mx + nmx + 1) \]

如果父边连上来,\(u\) 作为中间节点,可以继续向下选择一条最长子树链延伸,所以:

\[dp[u] = mx + 1 \]

\(dp[u]\) 的统一含义

\(dp[u]\) 表示:父边已经连上时,从 \(u\) 向下延伸的最长链(包含 \(u\))。

因为如果 \(u\) 能作为中间节点(\(son \ge 3\)),它一定选择向下延伸比作为端点更优;如果 \(u\) 只能作为端点(\(son = 2\)),则向下不能延伸。所以直接返回“父边已连时,从 \(u\) 向下延伸的最长链”即可。

根节点的特殊处理

根节点没有父边,所以 \(deg[1] = son[1]\),不能直接用 \(son + 1\) 的关系,需要单独判断:

  • 若 \(g[1].size() = 2\):\(deg[1] = 2\),可以作为长度为 \(1\) 的中心,\(ans = \max(ans, 1)\)。
  • 若 \(g[1].size() = 3\):\(deg[1] = 3\),可以作为端点,\(ans = \max(ans, mx + 1)\)。
  • 若 \(g[1].size() \ge 4\):\(deg[1] \ge 4\),可以作为中间节点,\(ans = \max(ans, mx + nmx + 1)\)。

其中 \(mx\) 和 \(nmx\) 是根节点子节点中最大的两个 \(dp\) 值。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vvi = vector<vector<int>>;
const int N = 2e5 + 10;

int dp[N];
int ans = 0;

void dfs(vvi& g, int u, int pa) {
    int mx = 0, nmx = 0, son = 0;
    for(auto &v : g[u]) {
        if(v == pa) continue;
        dfs(g, v, u);
        if(dp[v] >= mx) nmx = mx, mx = dp[v];
        else nmx = max(dp[v], nmx);
        son ++;
    }
    if(pa == -1) return;

    if(son == 1) ans = max(ans, 1);
    if(son == 2) {
        dp[u] = 1;
        ans = max(ans, mx + 1);
    }
    else if(son >= 3) {
        dp[u] = mx + 1;
        ans = max(ans, mx + nmx + 1);
    }
}

void solve() {
    int n; cin >> n;
    vvi g(n + 1);
    for(int i = 1; i < n; i ++) {
        int a, b; cin >> a >> b;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    fill(dp, dp + n + 1, 0);
    ans = 0;
    dfs(g, 1, -1);

    int mx = 0, nmx = 0;
    for(auto &v : g[1]) {
        if(dp[v] >= mx) nmx = mx, mx = dp[v];
        else nmx = max(dp[v], nmx);
    }
    if(g[1].size() == 2) ans = max(ans, 1);
    if(g[1].size() == 3) ans = max(ans, mx + 1);
    if(g[1].size() >= 4) ans = max(ans, mx + nmx + 1);

    cout << ans << "\n";
}

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    int _=1; cin >> _;
    while(_--) solve();
    return 0;
}
posted @ 2026-10-03 10:26  thenrify  阅读(5)  评论(0)    收藏  举报