树形DP一枚,table[i][j][0]表示从i出发访问j个节点并且返回到i所走的最小距离,table[i][j][1]表示从i出发访问j个节点但不用返回到i所走的最短距离
table[i][j][0] = min(table[i][j-k][0]+table[z][k][0]+2*dist[i][z])(其中z为i的儿子, 0 < k < num[z])
table[i][j][1] = min(table[i][j-k][0]+table[z][k][1]+dist[i][z], table[i][j-k][1]+table[z][k][0]+2*dist[i][z]) (其中z为i的儿子, 0 < k < num[z])
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::make_pair; using std::greater; using std::endl; const int MAXN(510); const int MAXM(MAXN); const int INFI((INT_MAX-1) >> 1); struct EDGE { int v, w; EDGE *next; }; EDGE *first[MAXN]; EDGE edge[MAXM]; EDGE *rear; void init() { memset(first, 0, sizeof(first)); rear = edge; } void insert(int tu, int tv, int tw) { rear->v = tv; rear->w = tw; rear->next = first[tu]; first[tu] = rear++; } int num[MAXN]; bool is_root[MAXN]; void dfs_num(int cur) { num[cur] = 1; for(EDGE *i = first[cur]; i; i = i->next) { dfs_num(i->v); num[cur] += num[i->v]; } } int table[MAXN][MAXN][2]; void dfs(int cur) { if(num[cur] == 1) { table[cur][1][0] = table[cur][1][1] = 0; return; } int tn = num[cur]; for(int i = 0; i <= tn; ++i) table[cur][i][0] = table[cur][i][1] = INFI; table[cur][1][0] = table[cur][1][1] = 0; for(EDGE *i = first[cur]; i; i = i->next) { dfs(i->v); for(int j = tn; j > 1; --j) { for(int k = min(num[i->v], j-1); k >= 1; --k) { table[cur][j][0] = min(table[cur][j][0], table[i->v][k][0]+table[cur][j-k][0]+2*i->w); table[cur][j][1] = min(table[cur][j][1], table[i->v][k][1]+table[cur][j-k][0]+i->w); table[cur][j][1] = min(table[cur][j][1], table[i->v][k][0]+table[cur][j-k][1]+2*i->w); } } } } int main() { int n; int n_case(0); while(scanf("%d", &n), n) { init(); memset(is_root, -1, sizeof(is_root)); int root; int tu, tv, tw; for(int i = 1; i < n; ++i) { scanf("%d%d%d", &tv, &tu, &tw); insert(tu, tv, tw); is_root[tv] = false; } for(int i = 0; i < n; ++i) if(is_root[i]) { root = i; break; } dfs_num(root); dfs(root); int q; scanf("%d", &q); printf("Case %d:\n", ++n_case); while(q--) { int x; scanf("%d", &x); int ans; for(ans = n; ans >= 1; --ans) if(table[root][ans][1] <= x) break; printf("%d\n", ans); } } return 0; }