试题编号: | 201909-5 |
试题名称: | 城市规划 |
时间限制: | 3.0s |
内存限制: | 512.0MB |
问题描述: |
![]() ![]() |
几乎是Gym102222G的原版,详解见上一篇博文
/*
贡献+树形dp+01背包
*/
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int M=N<<1;
const int Kn=105;
typedef long long ll;
int n,m,k;
int tot,to[M],nxt[M],head[N],ind[N],siz[N];ll val[M];bool vis[N];
ll f[N][Kn];
inline void add(int x,int y,ll z){
ind[x]++;to[++tot]=y;val[tot]=z;nxt[tot]=head[x];head[x]=tot;
}
void dfs(int u,int fa){
for(int l=head[u];l;l=nxt[l]){
int v=to[l];ll w=val[l];
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
for(int i=min(siz[u],k);i;i--){//逆序,背包问题, siz[u]个,每个都是选或者不选
for(int j=min(siz[v],i);j;j--){
f[u][i]=min(f[u][i],f[u][i-j]+f[v][j]+w*(k-j)*j);
}
}
}
};
void init_dp(){
for(int i=1;i<=n;i++){
f[i][0]=0;
for(int j=1;j<=m;j++) f[i][j]=1e17;
if(vis[i]) siz[i]=1,f[i][1]=0;
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1,x;i<=m;i++) scanf("%d",&x),vis[x]=1;
for(int i=1,x,y,z;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
int rt=1;
for(int i=1;i<=n;i++) if(ind[i]>1){rt=i;break;}
init_dp();
dfs(rt,0);
printf("%lld\n",f[rt][k]);
return 0;
}