题解
- 首先,显然不会有先传送回祖先再走同一条路下来的,这就不是最小值了;还有要经过所有点
- 那么就可以设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 }