點對最大值

題目鏈接:點對最大值


顯然可以樹dp。

dp[x]爲從子樹到點x的最大權值。

然後我們每次對一個點記錄,從子樹來的最大值和次大值。

每次轉移即可,或者是直接到根。

要注意初始值爲-1e9而不是0


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10,M=N<<1;
int dp[N],res,c[N],n;
int head[N],to[M],w[M],nex[M],tot;
inline void add(int a,int b,int c){to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;}
void dfs(int x,int fa){
	dp[x]=-1e9; int mx1=-1e9,mx2=-1e9;
	for(int i=head[x];i;i=nex[i])	if(to[i]!=fa){
		dfs(to[i],x); int tmp=w[i]+dp[to[i]];
		dp[x]=max(dp[x],tmp);
		if(tmp>mx1) mx2=mx1,mx1=tmp;
		else if(tmp>mx2) mx2=tmp; 
	}
	res=max(res,dp[x]+c[x]);
	res=max(res,mx1+mx2);
	dp[x]=max(dp[x],c[x]);
}
inline void solve(){
	cin>>n;	tot=0; memset(head,0,sizeof head); res=-1e9;
	for(int i=2,a,b;i<=n;i++)	scanf("%d %d",&a,&b),add(i,a,b),add(a,i,b);
	for(int i=1;i<=n;i++)	scanf("%d",&c[i]);
	dfs(1,0);	cout<<res<<endl;
}
signed main(){
	int T; cin>>T; while(T--) solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章