#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstdio>
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 城市规划
最新推荐文章于 2023-04-19 17:59:42 发布