[GESP2406 八级] 最远点对
题目传送门
本题可以知道,是求树的直径,但是得特判是否多出了黑色节点。
这道题我们可以使用树形dp。
因为我们有两种状态,分别是最后以黑色结尾和白色结尾。
dp就表示最多能走多远。
dp转移方程:
我们知道,对于id来说,我们可以最多走相邻的节点最多走的个数加一,并取max。
id有两种状态,分别是最后以黑色结尾和最后与白色结尾的情况。
然后,我们的ans为这些东西取max。
最后,我们输出即可。
//dp[id][i] 表示id在什么颜色结尾的情况下最久走多远
dp[id][i] = max(dp[id][i], dp[x][i] + 1);
dfs定义方式
void dfs(int id, int fa, int cnt/*表示有多少黑色节点*/, int cnt2/*表示一共经过了多少节点*/) {
if(cnt > k) { //特判:是否超过限制
return;
}
for(int x : v[id]) {
if(x == fa) { //判断是否走过该节点
continue;
}
dfs(x, id);
//转移方程
ans = max(ans, max(dp[id][2] + dp[x][1], dp[id][1] + dp[x][2]) + 1);
dp[id][1] = max(dp[id][1], dp[x][1] + 1);
dp[id][2] = max(dp[id][2], dp[x][2] + 1);
}
}
最后,易错点!!!
这里的话,记得一定是分清楚哪个代表黑,哪个代表白。
代码:
/**
* @file: [GESP2406 八级] 最远点对.cpp
* @author: xiaoshu
* @date: 2026-05-14 17:34:38
* 小暑的防伪
**/
#include "bits/stdc++.h"
#pragma GCC diagnostic ignored "-Wunused-variable"
#define Main signed main
#define int long long
#define ios_ return 0; \
ios_base::sync_with_stdio(0); \
ios::sync_with_stdio(0); \
const char endl = '\n'; \
cin.tie(nullptr); \
cout.tie(nullptr);
using namespace std;
int n;
int idx = 0;
int ans = 0;
int c[200010] = { };
int dp[200010][10] = { };
vector <int> v[200010];
void dfs(int id, int fa) {
dp[id][1] = INT_MIN;
dp[id][2] = INT_MIN;
dp[id][c[id] + 1] = 0;
for(int x : v[id]) {
if(x == fa) {
continue;
}
dfs(x, id);
ans = max(ans, max(dp[id][2] + dp[x][1], dp[id][1] + dp[x][2]) + 1);
dp[id][1] = max(dp[id][1], dp[x][1] + 1);
dp[id][2] = max(dp[id][2], dp[x][2] + 1);
}
}
Main() {
ios_;
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> c[i];
}
for(int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1, 0);
cout << ans << endl;
return 0;
}
posted on 2026-05-18 21:25 xiaoshu_ci 阅读(35) 评论(0) 收藏 举报
浙公网安备 33010602011771号