【CCF 201909-5】城市规划

参考链接

#include
#include
#include
#include
using namespace std;
const int maxn = 5e4 + 100;
#define TLE ios::sync_with_stdio(0),cin.tie(0)
const int INF = 0x3f3f3f3f;
struct Node {
    int v, w, next;
}node[maxn * 2];
bool idx[maxn];
int head[maxn];
long long dp[maxn][1005];
int temp_dp[maxn];
int n, m, k, temp = 0;
void AddNode(int u, int v, int w) { //邻接表;
    node[temp].v = v;
    node[temp].w = w;
    node[temp].next = head[u]; //标记以u为起点的所有联通路;
    head[u] = temp;
    temp++;
}
int num[maxn];
void dfs(int u, int fa) {
    /*
    dp[u][t] 的意义为: 以u为根节点的树中选择了t个重要节点(其它的所有节点中一共选了k-t个节点)
    为这棵树中的所有重要节点两两之间路径之和最小值所耗费的成本
    */
    dp[u][0] = 0;
    if (idx[u]) {
        dp[u][1] = 0;
        num[u] = 1; //以u为根节点的子树所包含的重要节点;
    }
    for (int i = head[u]; i != -1; i = node[i].next) {
        if (node[i].v == fa) continue;
        int v = node[i].v;
        int w = node[i].w;
        dfs(v, u);
        for (int j = 0; j <= k; j++)
            temp_dp[j] = dp[u][j];
        int mu = min(k, num[u]);
        int mv = min(k, num[v]);
        num[u] += num[v]; //更新;
        for (int j = 0; j <= mu; j++)
            for (int t = 0; t <= mv && t + j <= k; t++) {
                dp[u][j + t] = min(1ll * dp[u][j + t], temp_dp[j] + dp[v][t] + 1ll * (k - t) * t * w);
                /*printf("dp[%d][%d] : %d , j : %d , t : %d , temp_dp[%d] : %d , dp[%d][%d] : %d\n", u, j + t, dp[u][j + t], j, t,j,temp_dp[j],v,t,dp[v][t]);
                getchar();*/
            }
    }
}
int main() {
    TLE;
    memset(head, -1, sizeof(head));
    memset(idx, 0, sizeof(idx));
    scanf("%d %d %d", &n, &m, &k);
    int t;
    for (int i = 0; i < m; i++) {
        scanf("%d", &t);
        idx[t] = 1;
    }
    int ut, vt, wt;
    for (int i = 0; i < n-1; i++) {
        scanf("%d %d %d", &ut, &vt, &wt);
        AddNode(ut, vt, wt);
        AddNode(vt, ut, wt);
    }
    memset(dp, INF, sizeof(dp));
    dfs(1, -1);
    printf("%d\n", dp[1][k]);
    return 0;
}

你可能感兴趣的:(【CCF 201909-5】城市规划)