1. 程式人生 > >【NOIP2018模擬賽2018.10.17】傳送門 (portal)

【NOIP2018模擬賽2018.10.17】傳送門 (portal)

題目

在這裡插入圖片描述
在這裡插入圖片描述


題解

— 是樹形dp呢
f[x][0]:x和x的子樹裡沒有傳送門
f[x][1]:x和x的子樹裡有傳送門
如果不用傳送門的話,每條邊跑兩次(下去,回來)
用了的話,就只需要跑下去就行了,但是如果兒子用了傳送門,還是要跑回來的
(因為只能同時存在兩個傳送門)


程式碼

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std; const int MAXN=1e6+5; const long long null=1e15; int n; int head[MAXN],to[MAXN*2],next[MAXN*2],w[MAXN*2],cnt; long long f[MAXN][2],d[MAXN]; void add(int u,int v,int l){ cnt++; next[cnt]=head[u]; to[cnt]=v; w[cnt]=l; head[u]=cnt; } void dp(int x,int fa){ for(int i=head[
x];i;i=next[i]){ int y=to[i]; if(y==fa) continue; dp(y,x); d[x]=max(d[x],d[y]+w[i]); f[x][0]+=f[y][0]+2*w[i]; f[x][1]+=min(f[y][0]+w[i]-d[y],f[y][1]+w[i]*2); } } int main(){ // freopen("portal.in","r",stdin); // freopen("portal.out","w",stdout); cin>>n; for(int i=1;i<n;i++){ int
u,v,a; scanf("%d%d%d",&u,&v,&a); add(u,v,a); add(v,u,a); } dp(1,1); cout<<min(f[1][1],f[1][0]); return 0; }