题意
在达芬奇时代,有一个流行的儿童游戏称为连珠线。当然,这个游戏是关于珠子和线的。线是红色或蓝色的,珠子被编号为 11到 n。这个游戏从一个珠子开始,每次会用如下方式添加一个新的珠子:
Append(w, v):一个新的珠子 w 和一个已经添加的珠子 v 用红线连接起来。
Insert(w, u, v):一个新的珠子 w 插入到用红线连起来的两个珠子 u,v之间。具体过程是删去 u,v 之间红线,分别用蓝线连接 u,w 和 w,v。
每条线都有一个长度。游戏结束后,你的最终得分为蓝线长度之和。
给你连珠线游戏结束后的游戏局面,只告诉了你珠子和链的连接方式以及每条线的长度,没有告诉你每条线分别是什么颜色。
你需要写一个程序来找出最大可能得分。即,在所有以给出的最终局面结束的连珠线游戏中找出那个得分最大的,然后输出最大可能得分。
分析
不妨我们考虑从某个点开始,那么一定不存在一些跨越当前点的两个子树上来因为加入当前点而变成两条蓝色的边
那么我们考虑treedp,发现每次都要跨过两层点,其实我们只需要知道是不是中间的点即可, f[i][0/1] f [ i ] [ 0 / 1 ] 表示i子树内,i这个点是不是中间点的贡献
然后转移:
然后就有一个 N2 N 2 的dp了,常规的,考虑优化,只需要增加一个换跟操作
要记录某个点x从父亲过来的那条边的代价,还有以下的最大值和次大值:
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 200010;
const ll inf = 1e9;
inline ll read()
{
ll p=0; ll f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
struct node{ll x,y,next,d;}edge[N<<1]; ll len,first[N];
void ins(ll x,ll y,ll d){len++; edge[len].x=x; edge[len].y=y; edge[len].d=d; edge[len].next=first[x]; first[x]=len;}
ll f[N][2] , h1[N] , h2[N] , hp1[N] , hp2[N]; ll g[N][2];
void upd(ll &x,ll y){x = x+y;}
void updh(ll x,ll y,ll d)
{
if(h1[x] < d)
{
h2[x] = h1[x]; hp2[x] = hp1[x];
h1[x] = d; hp1[x] = y;
}
else if(h2[x] < d)
{
h2[x] = d; hp2[x] = y;
}
}
void dfs(ll x,ll fa)
{
f[x][0] = 0; h1[x] = h2[x] = -inf;
for(ll k=first[x];k!=-1;k=edge[k].next)
{
ll y = edge[k].y;
if(y==fa) continue;
dfs(y,x);
upd(f[x][0] , max(f[y][0] , f[y][1] + edge[k].d) );
updh(x , y , -max(f[y][0] , f[y][1] + edge[k].d) + f[y][0] + edge[k].d);
}f[x][1] = f[x][0] + h1[x];
}
ll ans = 0;
void dfs2(ll x,ll fa,ll d)
{
ans = max(ans , f[x][0] + max(g[x][0] , g[x][1] + d));
// if(f[x][0] + max(g[x][0] , g[x][1] + d) == 142) printf("%d\n",x);
for(ll k=first[x];k!=-1;k=edge[k].next)
{
ll y = edge[k].y;
if(y==fa) continue;
ll tmp = max(g[x][0] , g[x][1] + d);
ll g0 = tmp + f[x][0] - max(f[y][0] , f[y][1] + edge[k].d);
g[y][0] = g0;
if(hp1[x] == y) g[y][1] = g0 + max(h2[x] , -tmp + g[x][0] + d);
else g[y][1] = g0 + max(h1[x] , -tmp + g[x][0] + d);
dfs2(y,x,edge[k].d);
}
}
int main()
{
ll n = read(); len = 0; memset(first,-1,sizeof(first));
for(ll i=1;i<n;i++){ll x = read(); ll y = read(); ll d = read(); ins(x,y,d); ins(y,x,d);}
dfs(1,0);
g[1][0] = 0; g[1][1] = -inf; dfs2(1,0,-inf);
return printf("%lld\n",ans),0;
}