HDU 2196(树形dp)

Problem

HDU 题目地址

题意简述:给一个 (n) 个点的带边权树,求每个点能到的最远距离。

Solution

以前做过一遍没有理解透,现在理解透了。

题目要求每个点的答案,一般要用换根dp。这里有一种换根dp的实现方法————扫两次。

(dp[i,0/1/2]) 表示 (i) 点:(0) 向下延伸的最远距离,(1) 向下延伸的次远距离(且不与最远距离的路径重合),(2) 向上延伸的最远距离。其中 (0,1) 由第一次扫描得到,(2) 由第二次扫描得到,具体的:

(w)(i->j) 这条边的权值,在第一次 Dfs(扫描)中:

[dp[i,0] = max_{j in son_i}{dp[j,0] + w} ]

令上述中最大的 (j)(k) 点,那么

[dp[i,1] = max{max_{j in son_i,j ≠ k}{dp[j,0] + w},dp[k,1] + w} ]

在第二次扫描中,(w) 类似:

如果 (i) 点是 (fa_i) 最远距离上的点 (dp[i,2] = max{dp[fa_i,1],dp[fa_i,2]} + w)

否则 (dp[i,2] = max{dp[fa_i,0],dp[fa_i,2]} + w)

Code

Talk is cheap.Show me the code.

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read() {
	int x=0,f=1; char ch=getchar();
	while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
	return x * f;
}
const int N = 1e5+7;
int n,cnt;
int head[N];
int f[N][3];
struct Edge {
	int next,to,w;
}edge[N<<1];
inline void add(int u,int v,int w) {
	edge[++cnt] = (Edge)<%head[u],v,w%>;
	head[u] = cnt;
}
void Dfs1(int u,int fa) {
	int Mxk = 0;
	for(int i=head[u];i;i=edge[i].next) {
		int v = edge[i].to, w = edge[i].w;
		if(v == fa) continue;
		Dfs1(v,u);
		if(f[v][0]+w >= f[u][0]) f[u][1] = f[u][0], f[u][0] = f[v][0]+w;
		else if(f[v][0]+w > f[u][1]) f[u][1] = f[v][0]+w; 
	}
}
void Dfs2(int u,int fa,int prew) {
	if(f[fa][0] == f[u][0]+prew) f[u][2] = f[fa][1] + prew;
	else f[u][2] = f[fa][0] + prew;
	f[u][2] = max(f[u][2],f[fa][2]+prew);
	for(int i=head[u];i;i=edge[i].next) {
		int v = edge[i].to, w = edge[i].w;
		if(v == fa) continue;
		Dfs2(v,u,w);
	}
}
void test() {
	puts("test");
	for(int i=1;i<=n;++i)
		printf("	%lld %lld %lld
",f[i][0],f[i][1],f[i][2]);
	puts("--End--");
}
void work() {
	memset(head, 0, sizeof(head)); cnt = 0;
	memset(f, 0, sizeof(f));
	for(int i=2,fa,w;i<=n;++i) {
		fa = read(), w = read();
		add(i,fa,w), add(fa,i,w);
	}
	Dfs1(1,0); Dfs2(1,0,0);
	//test();
	for(int i=1;i<=n;++i)
		printf("%lld
",max(max(f[i][0],f[i][1]),f[i][2]));
}
signed main()
{
	while(~scanf("%lld",&n))
		work();
	return 0;
}
/*
5
1 1
2 1
3 1
1 1

3
2
3
4
4
*/

Summary

无。

原文地址:https://www.cnblogs.com/BaseAI/p/12267354.html