HDU 4003 Find Metal Mineral(树形背包DP)

Find Metal Mineral

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

const int N = 10100;

struct Node {
    int to;
    int cap;
};

vector<Node> v[N];
int dp[N][12], vis[N];
//dp[i][j] 用 j 个机器人去采以 i 为根节点的子树的所有矿石的最小花费

int n, s, k;
void dfs(int father) {
    vis[father] = 1;

    for(int i = 0; i < v[father].size(); i++) {
        Node child = v[father][i];
        if(vis[child.to] == 1)
            continue;

        dfs(child.to);

        for(int num = k; num >= 0; num--) { //注意0
            dp[father][num] += dp[child.to][0] + 2*child.cap;//最大结果,派下去又返回father
            for(int j = 1; j <= num; j++)
                dp[father][num] = min(dp[father][num], dp[father][num-j] + dp[child.to][j] + j*child.cap);
                //派j个机器人给v子树就会经过father-child之间的边j次
        }
    }
}

int main() {
    freopen("data.in", "r", stdin);
    while(~scanf("%d%d%d", &n, &s, &k)) {
        for(int i = 0; i < n-1; i++) {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            Node tmp;
            tmp.to = y;
            tmp.cap = z;
            v[x].push_back(tmp);\

            tmp.to = x;
            v[y].push_back(tmp);
        }

        memset(vis, 0, sizeof(vis));
        memset(dp, 0, sizeof(dp));

        dfs(s);

        printf("%d\n",dp[s][k]);
        for(int i=1; i<=n; i++)
            v[i].clear();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ccshijtgc/article/details/81219118