csp 201909-5 城市规划 (DP)

    科技2022-09-07  110

    题目链接

    http://118.190.20.162/view.page?gpid=T90

    解题思路

    考虑DP,F[i][j]表示i子树中选j个点的代价,注意到某个子树与父亲相连的边的代价只与子树选的点个数有关,可以在转移时对每条边计算代价。 DP转移: F[i][j]=min{F[i][j-k]+F[son][k]+k ∗ \ast (K-k) ∗ \ast c},k为子树选取点个数,c为边代价。 时间复杂度O(NK^2)

    代码

    #include <bits/stdc++.h> using namespace std; const int MAXN=50010; const long long INF=1LL<<60; int tot,head[MAXN]; struct Edge {int to,net,v;}E[MAXN<<1]; void addedge(int x,int y,int v) { E[++tot].to=y;E[tot].net=head[x];head[x]=tot;E[tot].v=v; E[++tot].to=x;E[tot].net=head[y];head[y]=tot;E[tot].v=v; } int N,M,K,fa[MAXN],size[MAXN];long long F[MAXN][210];bool Mark[MAXN]; void dfs(int x) { for (int i=1;i<=K;++i) F[x][i]=INF; if (Mark[x]) size[x]=1,F[x][1]=0; for (int i=head[x];i;i=E[i].net) if (E[i].to!=fa[x]) { fa[E[i].to]=x; dfs(E[i].to); size[x]+=size[E[i].to]; for (int j=min(K,size[x]);j;--j) { int v=min(size[E[i].to],min(K,j)); for (int k=1;k<=v;++k) F[x][j]=min(F[x][j],F[x][j-k]+F[E[i].to][k]+1LL*(K-k)*k*E[i].v); } } } int main() { cin>>N>>M>>K; for (int i=1;i<=M;++i) { int x; scanf("%d",&x); Mark[x]=true; } for (int i=1;i<N;++i) { int x,y,v; scanf("%d%d%d",&x,&y,&v); addedge(x,y,v); } dfs(1); cout<<F[1][K]<<endl; return 0; }
    Processed: 0.008, SQL: 9