[树形dp] Jzoj P5906 传送门
题解
- 首先,显然不会有先传送回祖先再走同一条路下来的,这就不是最小值了;还有要经过所有点
- 那么就可以设f[i][0/1]为走完i的子树回到i是否适用传送门的最小逃脱时间
- 状态转移方程显然 f[i][0]+=f[son][0]+v*2 f[x][1]+=min(f[son][0]+e[i].v-d[son],f[son][1]+v*2)
- d数组为最小层叶子节点到x的最长距离
代码
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 struct edge {int to,from,v;}e[1000010*2]; 5 int n,head[1000010],cnt; 6 long long f[1000010][2],d[1000010]; 7 bool insert(int x,int y,int z) { e[++cnt].to=y; e[cnt].from=head[x]; e[cnt].v=z; head[x]=cnt; } 8 void dfs(int x,int fa) 9 { 10 for (int i=head[x];i;i=e[i].from) 11 if (e[i].to!=fa) 12 dfs(e[i].to,x),d[x]=max(d[x],d[e[i].to]+e[i].v), 13 f[x][0]+=f[e[i].to][0]+e[i].v*2,f[x][1]+=min(f[e[i].to][0]+e[i].v-d[e[i].to],f[e[i].to][1]+e[i].v*2); 14 } 15 int main() 16 { 17 freopen("portal.in","r",stdin),freopen("portal.out","w",stdout); 18 scanf("%d",&n); 19 for (int i=1,x,y,z;i<=n-1;i++) scanf("%d%d%d",&x,&y,&z),insert(x,y,z),insert(y,x,z); 20 dfs(1,0); 21 printf("%lld",f[1][1]); 22 }