CF1083A The Fair Nut and the Best Path

CF1083A The Fair Nut and the Best Path

  • 先把边权搞成点权(其实也可以不用),那么就是询问树上路径的最大权值.
  • 任意时刻权值非负的限制可以不用管,因为若走路径 (u o v) ,走到 (w) 权值为负数了,那么直接从 (w) 下一个点开始走显然更优.这个限制是多余的.
  • 那么问题就很简单了,经典 (dp) 做法,记 (f(i))(i) 子树内一点到 (i) 所有路径中的最大权值, (O(n)) 即可解决问题.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
	int x=0;
	bool pos=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar())
		if(ch=='-')
			pos=0;
	for(;isdigit(ch);ch=getchar())
		x=x*10+ch-'0';
	return pos?x:-x;
}
const int MAXN=6e5+10;
int cnt,head[MAXN],to[MAXN<<1],nx[MAXN<<1];
int w[MAXN];
inline void addedge(int u,int v)
{
	++cnt;
	to[cnt]=v;
	nx[cnt]=head[u];
	head[u]=cnt;
	swap(u,v);
	++cnt;
	to[cnt]=v;
	nx[cnt]=head[u];
	head[u]=cnt;
}
int n;
ll f[MAXN];
ll ans=0;
void upd(ll x,ll &mx,ll &sc)
{
	if(x>=mx)
		sc=mx,mx=x;
	else if(x>sc)
		sc=x;
}
void dfs(int u,int fa)
{
	ll mx=0,sc=0;
	for(int i=head[u];i;i=nx[i])
		{
			int v=to[i];
			if(v==fa)
				continue;
			dfs(v,u);
			upd(f[v],mx,sc);
		}
	f[u]=mx+w[u];
	ans=max(mx+sc+w[u],ans);
}
int main()
{
	n=read();
	for(int i=1;i<=n;++i)
		w[i]=read();
	for(int i=1;i<n;++i)
		{
			int u=read(),v=read();
			addedge(u,i+n);
			addedge(v,i+n);
			w[i+n]=-1*read();
		}
	dfs(1,0);
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/jklover/p/10418077.html