首页 > 其他 > 详细

HDU - 2196 Computer(二次扫描+换根法树形dp)

时间:2021-04-01 23:41:37      阅读:25      评论:0      收藏:0      [点我收藏+]

题目链接

题目大意

??求树上每个点到其他点的最大距离。

解题思路

??首先随便选择一个顶点作为根然后跑一遍dfs,记录每个顶点以其为根能到达的最大深度和次大深度,然后再跑一遍dfs,对于每个顶点,如果要到达一个距离最大的点,要么就是原来中的子树中的距离最大的点,要么就是经过父节点的某个点。

代码

const int maxn = 1e4+10;
const int maxm = 1e6+10;
vector<int> e[maxn];
int n, w[maxn], son[maxn]; 
ll dp[maxn][3];   /*dp[u][0]是原子树中距离u最远的距离,
son[v]是距离u最远的顶点,dp[u][1]是次元距离,dp[u][2]是经过父节点的最远距离*/
void dfs1(int u) {
	for (auto v : e[u]) {
		dfs1(v);
		ll len = dp[v][0]+w[v]; int t = v;
		if (dp[u][0]<len) {
			swap(len, dp[u][0]);
			swap(t, son[u]);
		}
		if (dp[u][1]<len) dp[u][1] = len;
	}
}
void dfs2(int u) {
	for (auto v : e[u]) {
		if (son[u]==v) dp[v][2] = max(dp[u][1], dp[u][2])+w[v];
		else dp[v][2] = max(dp[u][0], dp[u][2])+w[v];
		dfs2(v);
	}
}
void init() {
	for (int i = 0; i<=n; ++i) {
		e[i].clear();
		dp[i][0] = dp[i][1] = dp[i][2] = 0;
	}
}
int main() { 
	while(cin >> n) {
		init();
		for (int i = 2, a; i<=n; ++i) {
			cin >> a >> w[i];
			e[a].push_back(i);
		}
		dfs1(1); dfs2(1);
		for (int i = 1; i<=n; ++i) cout << max(dp[i][0], dp[i][2]) << endl;
	}
    return 0;
}

HDU - 2196 Computer(二次扫描+换根法树形dp)

原文:https://www.cnblogs.com/shuitiangong/p/14608315.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!