试题编号: | 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 ",f[rt][k]); return 0; }