CCF 201909-5 推荐系统

试题编号: 201909-5
试题名称: 城市规划
时间限制: 3.0s
内存限制: 512.0MB
问题描述:

几乎是Gym102222G的原版,详解见上一篇博文

/*
贡献+树形dp+01背包
*/
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+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=0;
    for(int i=1;i<=n;i++) if(ind[i]>1){rt=i;break;}
    init_dp();
    dfs(rt,-1);
    printf("%lld\n",f[rt][k]);
    return 0;
}
/*
5 3 2
1 3 5
1 2 4
1 3 5
1 4 3
4 5 1
*/

猜你喜欢

转载自www.cnblogs.com/shenben/p/11990300.html