[51nod1812]树的双直径 树形DP

[51nod1812]

  • f[x]表示x子树内最长链的长度,h[x]表示除去x即其子树的最长链长度
  • 注意栈空间
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define ll __int128
using namespace std;
const ll inf=1e9;
const ll N=4e5+100;
struct node{int y,n;ll v;}e[N<<1];
struct Q{ll v;int id;}a[N];
ll dmax[N],f1[N],h1[N],ans1,ans2,cnt=0,len,n,m,x,y,v;
int lin[N<<1];
ll ans=-inf;
void Prll(ll x){if(x>9)Prll(x/10);putchar(x%10+'0');}
void read(ll x,ll y,ll v)
{e[++len].y=y,e[len].v=v,e[len].n=lin[x],lin[x]=len;}
bool cmp(Q a,Q b){return a.v>b.v;}
void dfs(ll x,ll fa){
	ll flag=0;
	for(ll i=lin[x];i;i=e[i].n){
		ll y=e[i].y;
		if(y==fa)continue;
		dfs(y,x); flag=1;
		f1[x]=max(f1[x],f1[y]);
		f1[x]=max(f1[x],dmax[x]+dmax[y]+e[i].v);
		dmax[x]=max(dmax[x],dmax[y]+e[i].v);
	}
}
void DFS(ll x,ll fa,ll dis){
	cnt=0; a[++cnt].v=dis; a[cnt].id=-1;
	for(ll i=lin[x];i;i=e[i].n){
		ll y=e[i].y;
		if(y==fa)continue;
		a[++cnt].v=dmax[y]+e[i].v; a[cnt].id=y;
	}
	sort(a+1,a+cnt+1,cmp);
	
	for(ll i=lin[x];i;i=e[i].n){
		ll y=e[i].y;
		if(y==fa)continue;
		ll tot=0,sum=0;
		for(ll j=1;j<=cnt&&tot<2;j++){
			if(a[j].id==y)continue;
			tot++,sum+=max((ll)0,a[j].v);
		}
		h1[y]=max(sum,h1[x]);
	}
	ll p1=a[1].id,p2=a[2].id,p3=a[3].id,max1=a[1].v,max2=a[2].v,max3=a[3].v;
	for(ll i=lin[x];i;i=e[i].n){
		ll y=e[i].y;
		if(y==fa)continue;
		if(p1==y){
			if(p2==y){
				DFS(y,x,max((ll)0,max3)+e[i].v);
			}else DFS(y,x,max((ll)0,max2)+e[i].v);
		}else DFS(y,x,max((ll)0,max1)+e[i].v);
	}
}
void dfs2(ll x,ll fa,ll maxn){
	cnt=0; a[++cnt].v=maxn,a[cnt].id=-1;
	ans=max(ans,(ll)f1[x]*maxn);
	for(ll i=lin[x];i;i=e[i].n){
		ll y=e[i].y;
		if(y==fa)continue;
		a[++cnt].v=f1[y],a[cnt].id=y;
	}
	sort(a+1,a+cnt+1,cmp);
	ll MAX1=a[1].v,MAX2=a[2].v,P1=a[1].id,P2=a[2].id;
	for(ll i=lin[x];i;i=e[i].n){
		ll y=e[i].y;
		if(y==fa)continue;
		if(P1==y){
			dfs2(y,x,MAX2);
		}else dfs2(y,x,MAX1);
	}
}
ll R(){
	ll num=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))num=num*10+ch-'0',ch=getchar();
	return num*f;
}
int main()
{
	n=R();
	rep(i,2,n){x=R(),y=R(),v=R();read(x,y,v),read(y,x,v);}
	dfs(1,1); DFS(1,1,0); dfs2(1,1,0);
	rep(i,1,n)ans=max(ans,f1[i]*h1[i]);
	rep(i,1,len)e[i].v*=-1;
	memset(f1,0,sizeof(f1));
	memset(h1,0,sizeof(h1));
	memset(dmax,0,sizeof(dmax));
	dfs(1,1); DFS(1,1,0); dfs2(1,1,0);
	rep(i,1,n)ans=max(ans,f1[i]*h1[i]);
	Prll(ans);
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值