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;
}

浙公网安备 33010602011771号