This question is a POJ1849 version.
Let's start with a very important conclusion, the following two methods are based on this conclusion.
A person from the beginning to traverse a tree, if eventually to return to the starting point, the minimum weight passed is twice times the weight of the whole tree .
and k personal situation is so, the big deal only one person to go, the other K-1 people do not move on the line.
And the topic said these people are not better than back to the original point, so think of ways to consider which way to go , and finally with the whole tree weight of twice times less good.
One
Most of the practice is group backpack, recommend this blog.
The definition of the state of the inside is not complicated, and the idea is quite new than that of the online ones.
F (i, j) indicates that I is the root of the subtree has J robot set off, traverse this subtrees tree can walk less how many road.
The final answer is Sum-f (S, K)
1#include <iostream>2#include <cstdio>3#include <cstring>4#include <vector>5#include <algorithm>6 using namespacestd;7 8 Const intMAXN =10000+Ten;9 Const intMAXK = A;Ten One intN, S, K; A -vector<int>G[MAXN], C[MAXN]; - the intF[MAXN][MAXK]; - - voidDP (intUintFA) - { + for(inti =0; I < g[u].size (); i++) - { + intv = g[u][i], W =C[u][i]; A if(v = = FA)Continue; at DP (V, u); - for(inti = k; I >=1; i--) - for(intj =1; J <= I; J + +) -F[u][i] = max (F[u][i], f[u][i-j] + f[v][j] + (2-J) *W); - } - } in - intMain () to { + while(SCANF ("%d%d%d", &n, &s, &k) = =3) - { the for(inti =1; I <= N; i++) {g[i].clear (); C[i].clear (); } * $ intsum =0;Panax Notoginseng for(inti =1; I < n; i++) - { the intU, V, W; scanf"%d%d%d", &u, &v, &W); +Sum + =W; A G[u].push_back (v); C[u].push_back (w); the g[v].push_back (U); C[v].push_back (w); + } -Sum <<=1; $ $Memset (F,0,sizeof(f)); -DP (S,0); -printf"%d\n", Sum-f[s][k]); the } - Wuyi return 0; the}
code June
Two
In this blog post
A more ingenious approach is to find the longest path each time from the starting point, record the length of the path, and then turn the weight on the top of the path to the opposite number. Notice that the side that has become negative will no longer change back.
This way to find the longest path of K, and then add up is the most number of ways to walk.
Why should you turn the weight into a negative, because the second time you go this way for the third time, it means to walk away from the negative weight, that is, more away. If all the roads are negative, then the longest path in the tree is 0, that is, the robot is still in place.
1#include <iostream>2#include <cstdio>3#include <algorithm>4#include <cstring>5#include <vector>6 using namespacestd;7 8 Const intMAXN =10000+Ten;9 Ten structEdge One { A intu, V, W; -Edge (intUintVintW): U (U), V (v), W (w) {} - }; the -Vector<edge>edges; -vector<int>G[MAXN]; - + voidAddedge (intUintVintW) - { + Edges.push_back (Edge (U, V, W)); A Edges.push_back (Edge (V, U, W)); at intm =edges.size (); -G[u].push_back (M-2); -G[v].push_back (M-1); - } - - intN, S, K; in - intlen, id; to intPRE[MAXN]; + - voidDfsintUintFaintd) the { * if(d > Len) {len = D; id =u;} $ for(inti =0; I < g[u].size (); i++)Panax Notoginseng { -edge& e =Edges[g[u][i]]; the intv =e.v; + if(v = = FA)Continue; APRE[V] =G[u][i]; theDFS (V, u, D +E.W); + } - } $ $ intMain () - { - while(SCANF ("%d%d%d", &n, &s, &k) = =3) the { - edges.clear ();Wuyi inttot =0; the for(inti =1; I <= N; i++) g[i].clear (); - for(inti =1; I < n; i++) Wu { - intU, V, W; scanf"%d%d%d", &u, &v, &W); AboutTot + =W; $ Addedge (U, V, W); - } -Tot <<=1; - A intAns =0; + for(inti =0; I < K; i++) the { -Len =0, id =s; $Pre[s] =-1; theDFS (S,0,0); the if(id = = s)Continue; theAns + =Len; the for(intu = ID; U! = S; U =edges[pre[u]].u) - { in int& w =EDGES[PRE[U]].W; the if(W >0) W =-W; the } About } the theprintf"%d\n", Tot-ans); the } + - return 0; the}
code June
HDU 4003 Find Metal Mineral