51nod 树的双直径 树形DP

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/88637012

title

51nod

analysis

题解就看 Y Y YY 吧。
因为我也不是很会。

code

#include<bits/stdc++.h>
#define int long long
#define ll __int128
using namespace std;
const int maxn=4e5+10;
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1,ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}
inline void write(ll x)
{
	if (x>=10) write(x/10);
	putchar((x%10)+48);
}
int ver[maxn<<1],edge[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y,int z)
{
	ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
ll predown[maxn],ppredown[maxn],prebest[maxn];
ll sufdown[maxn],ssufdown[maxn],sufbest[maxn];
ll best[maxn],down[maxn],up[maxn];
inline void dfs(int x,int fa)
{
	ll Max=0,MMax=0;//Max 最长链,MMAx 次长链
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i];
		if (y==fa) continue;
		dfs(y,x);
		int t=down[y]+edge[i];
		if (t>Max)
		{
			MMax=Max;
			Max=t;
		}
		else if (t>MMax)
			MMax=t;
		best[x]=max(best[x],best[y]);
	}
	down[x]=Max;
	best[x]=max(best[x],MMax+Max);
}
ll ans=-1;
inline void solve()
{
	queue<pair<int,int> >q;
	q.push(make_pair(1,0));
	while (!q.empty())
	{
		int x=q.front().first,fa=q.front().second;
		q.pop();
		vector<pair<int,int> >child;
		child.push_back(make_pair(0,0));
		for (int i=head[x];i;i=Next[i])
		{
			int y=ver[i];
			if (y==fa) continue;
			child.push_back(make_pair(y,edge[i]));
		}
		//求前缀
		int siz=child.size();
		predown[0]=ppredown[0]=prebest[0]=0;
		for (int i=1;i<siz;++i)
		{
			int y=child[i].first,z=child[i].second;
			prebest[i]=max(prebest[i-1],best[y]);
			predown[i]=predown[i-1];
			ppredown[i]=ppredown[i-1];
			//
			if (predown[i]<down[y]+z)
			{
				ppredown[i]=predown[i];
				predown[i]=down[y]+z;
			}
			else if (ppredown[i]<down[y]+z)
				ppredown[i]=down[y]+z;
		}
		//求后缀
		sufdown[siz]=ssufdown[siz]=sufbest[siz]=0;
		for (int i=siz-1;i>=1;--i)
		{
			int y=child[i].first,z=child[i].second;
			sufbest[i]=max(sufbest[i+1],best[y]);
			sufdown[i]=sufdown[i+1];
			ssufdown[i]=ssufdown[i+1];
			//
			if (sufdown[i]<down[y]+z)
			{
				ssufdown[i]=sufdown[i];
				sufdown[i]=down[y]+z;
			}
			else if (ssufdown[i]<down[y]+z)
				ssufdown[i]=down[y]+z;
		}
		//
		for (int i=1;i<siz;++i)
		{
			int y=child[i].first;
			ll outside=up[x]+max(predown[i-1],sufdown[i+1]);
			outside=max(outside,predown[i-1]+ppredown[i-1]);
			outside=max(outside,sufdown[i+1]+ssufdown[i+1]);
			outside=max(outside,predown[i-1]+sufdown[i+1]);
			outside=max(outside,max(prebest[i-1],sufbest[i+1]));
			if (outside*best[y]>ans) ans=outside*best[y];
		}
		for (int i=1;i<siz;++i)
		{
			int y=child[i].first,z=child[i].second;
			up[y]=z+max(up[x],max(predown[i-1],sufdown[i+1]));
			q.push(make_pair(y,x));
		}
	}
}
signed main()
{
	int n;read(n);
	for (int i=1;i<n;++i)
	{
		int x,y,z;
		read(x);read(y);read(z);
		add(x,y,z);add(y,x,z);
	}
	dfs(1,0);
	solve();
	for (int i=1;i<=len;++i)
		edge[i]=-edge[i];
	memset(best,0,sizeof(best));
	memset(down,0,sizeof(down));
	memset(up,0,sizeof(up));
	dfs(1,0);
	solve();
	write(ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/88637012