[Solution] bzoj4033: [HAOI2015] Coloring on trees* (dynamic programming)

bzoj4033 , too lazy to copy, poke me poke me

Solution:

  • The definition state \(dp[i][j]\) represents the maximum contribution value when the subtree with the \(i\) node as the root node has \(j\) black nodes in it
  • Then we need to know that the number of times the edge from the child node to the root node will be calculated is: the number of white nodes in the subtree \(*\) the number of white nodes outside the subtree \(+\) the number of black nodes in the subtree \(* \) The number of black nodes outside the subtree
    \[dp[u][j+k]=max(dp[u][j+k],\]
    \[dp[u][j]+dp[v][k ]+(1ll)*k*(mk)*dis[v]+(1ll)*(siz[v]-k)*(nm-siz[v]+k)*dis[v])\]
  • drop a link

Attention:

  • Backpack dp on the tree pay attention to the operation:
  • In this way, the time complexity can be guaranteed to be \(O(n^2)\) , and each time it is guaranteed to be pushed from the obtained dp value to the unknown, there will be no redundant operations, so we need to add each enumeration The number of nodes is added to the number of nodes in the previous subtrees that have been calculated.

    for(int j=min(m,siz[u]);j>=0;j--){
      int box=min(m,siz[v]);
      for(int k=box;k>=0;k--){
         dp[u][j+k]=max(dp[u][j+k],dp[u][j]+dp[v][k]+1ll*k*(m-k)*dis[v]+1ll*(siz[v]-k)*(n-m-siz[v]+k)*dis[v]);
      }
    }siz[u]+=siz[v];

Code:

//It is coded by Ning_Mew on 4.24
#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int maxn=2000+7;

int n,m,fa[maxn];
LL dp[maxn][maxn];
int siz[maxn],dis[maxn];
int head[maxn],cnt=0;
struct Edge{int nxt,to,dis;}edge[maxn*2];

void add(int from,int to,int dis){
  edge[++cnt].nxt=head[from];
  edge[cnt].to=to;
  edge[cnt].dis=dis;
  head[from]=cnt;
}

void dfs(int u){
  siz[u]=1;//dp[u][0]=dp[u][1]=0;
  for(int i=head[u];i!=0;i=edge[i].nxt){
    int v=edge[i].to; if(v==fa[u])continue;
    dis[v]=edge[i].dis; fa[v]=u;
    dfs(v); //siz[u]+=siz[v];
    for(int j=min(m,siz[u]);j>=0;j--){
      int box=min(m,siz[v]);
      for(int k=box;k>=0;k--){
    dp[u][j+k]=max(dp[u][j+k],dp[u][j]+dp[v][k]+1ll*k*(m-k)*dis[v]
             +1ll*(siz[v]-k)*(n-m-siz[v]+k)*dis[v]);
      }
    }siz[u]+=siz[v];
  }return;
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n-1;i++){
    int u,v,diss;scanf("%d%d%d",&u,&v,&diss);
    add(u,v,diss);add(v,u,diss);
  }
  dfs(1);
  printf("%lld\n",dp[1][m]);
  return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325059174&siteId=291194637