CCF 201909-5 城市規划


 

試題編號: 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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM