# ZOJ 4031 Game on a Tree 树形DP

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5772

BaoBao is playing a game on a rooted tree with vertices and weighted edges. At the beginning of the game, a chess piece is placed on the root of the tree, which is vertex 1.

In each step, BaoBao can perform one of the four operations:

Move the chess piece along an edge from its current vertex to a child vertex. This operation will cost BaoBao units of value, where is the weight of the edge.

Jump the chess piece back to vertex 1. This operation is free and won’t cost BaoBao any unit of value.

Set a “save point” on the current vertex of the chess piece. If a save point has been set on some other vertex before, the save point on the old vertex will be removed (so there will be at most one save point on the tree at the same time). This operation is free and won’t cost BaoBao any unit of value.

Jump the chess piece back to the save point (the save point must be set before this operation). This operation is free and won’t cost BaoBao any unit of value.

The goal of the game is to visit every leaf vertex of the tree using the chess piece. Please help BaoBao calculate the minimum units of value he has to spend to achieve the goal.

Recall that a leaf vertex of a tree is a vertex with no child.

Input
There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains one integer (), indicating the size of the tree.

The following lines each contains three integers , and (, ), indicating an edge connecting vertex and vertex with weight in the tree.

It’s guaranteed that the given graph is a tree, and the sum of over all test cases will not exceed 2000.

Output
For each test case output one line containing one integer, indicating the minimum units of value BaoBao has to spend to achieve the goal.

Sample Input
3
8
1 2 1
3 1 1
2 4 2
5 4 2
6 2 2
3 7 3
8 3 3
8
1 2 1
2 3 1
3 4 1
3 5 1
2 6 1
6 7 1
6 8 1
8
1 2 100
2 3 1
3 4 1
3 5 1
2 6 1
6 7 1
6 8 1
Sample Output
14
8
107

1。 从父亲节点走向儿子节点
2。跳回一号起点
3。将当前结点设置为存档点，存档点在同一时刻只能存在一个
4。跳回存档点

1。 遍历完一颗子树后， 跳到1号结点 然后再走到cur
2。 讲cur设置为存档点，遍历完子树后直接进行4操作跳回cur

# 看错题目了，以为可以从子节点回到父节点 找了好久BUG。。。。

。。。 5/8号更新。。

if(dis[v]+dp[v][0]<sizes[v]*edge[i].w+dp[v][1]){
val = dis[v]+dp[v][0];
cnt = max(cnt,val-(edge[i].w+dp[v][0]));
}else{
val = sizes[v]*edge[i].w+dp[v][1];
cnt = max(cnt,val-(edge[i].w+dp[v][0]));
}

1。 将cur节点设置为存档点 2。 遍历完子树后 返回1节点 再走到cur节点。

dp[cur][0]=dp[cur][1]-MAX(cost);

md 题目没想清楚就写题解真的是太脑残了。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<time.h>
#include<math.h>
using namespace std;
typedef long long LL;
LL dp[205][2];// 定义DP[cur][0/1] 表示遍历cur节点的子树叶子节点，1表示返回该cur 0表示不返回cur.
const int MAX=1e3+10;
class Edge{
public:
LL u,v,next,w;
};
int tot=0;
Edge edge[MAX];
edge[tot].u=u;
edge[tot].v=v;
edge[tot].w=w;
}
LL sizes[MAX];// 该节点有多少个叶子节点
LL dis[MAX];// 该1节点到该节点的距离
int du[205];// 可以表示节点的子节点数
void dfs(int u,int per){
if(du[u]<=1){
sizes[u]=1;
}else{
sizes[u]=0;
}
LL cnt=0;
int v=edge[i].v;
if(v==per) continue;
dis[v]=dis[u]+edge[i].w;
dfs(v,u);
LL val;
sizes[u]+=sizes[v];
if(dis[v]+dp[v][0]<sizes[v]*edge[i].w+dp[v][1]){
val = dis[v]+dp[v][0];
cnt = max(cnt,val-(edge[i].w+dp[v][0]));
}else{
val = sizes[v]*edge[i].w+dp[v][1];
cnt = max(cnt,val-(edge[i].w+dp[v][0]));
}
dp[u][0]+=val;
dp[u][1]+=val;
}
dp[u][0]-=cnt;
}
int main(){
int T;
cin>>T;
while(T--){
int n;
scanf("%d",&n);
memset(dp,0,sizeof dp);
memset(dis,0,sizeof dis);
memset(du,0,sizeof du);
memset(sizes,0,sizeof sizes);
tot=0;
for(int i=1;i<n;i++){
LL u,v,w;
scanf("%lld %lld %lld",&u,&v,&w);
du[u]++;
du[v]++;
}