Factories(树上背包转移 树形dp)
作者:互联网
original link - https://nanti.jisuanke.com/t/41291
题意:
给出一棵树,你需要选择K个叶子,使得两两距离和最小。
解析:
考虑从儿子到父亲的转移,用dp[i][j]记录i的子树中,选取j个叶子的预期最小距离。
转移的时候用背包进行转移,将dp[son][h]当作一个物品,做只能选择一个物品的01包即可。
dp[fa][j]+dp[son][h]+lengthedge∗h∗(k−h))→dp[fa][j+h]
父亲已经有j条,我现在连入h条,对将来所产生的贡献为lengthedge∗h∗(k−h),因为一共会有h∗(k−h)对点经过这条边。
极限数据卡不到1e6∗100∗100
因为每个点的转移状态都是现有状态*儿子状态,均摊下来不会很大(上面的情况每个点只有1*100)
代码:
/*
* Author : Jk_Chen
* Date : 2019-08-31-20.11.43
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n';
const LL mod=1e9+7;
const int maxn=1e5+9;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
/*_________________________________________________________head*/
#define rep_e(i,p,u) for(int i=head[p],u=to[i];i;i=nex[i],u=to[i])
int head[maxn],to[maxn<<1],nex[maxn<<1],val[maxn<<1],now;
void add(int a,int b,int v){
nex[++now]=head[a];head[a]=now;to[now]=b,val[now]=v;
}
void init_edge(){
memset(head,0,sizeof head);
now=0;
}
/*_________________________________________________________edge*/
const LL inf=2e18;
int n,k;
int deg[maxn];
int siz[maxn];
LL dp[maxn][104];
void dfs(int p,int fa){
dp[p][0]=0;
siz[p]=0;
int lef=1;
rep_e(i,p,u){
if(u==fa)continue;
lef=0;
dfs(u,p);
siz[p]+=siz[u];
per(j,k-1,0){
if(dp[p][j]==inf)continue;
int up=min(k-j,siz[u]);
rep(h,1,up){
dp[p][j+h]=min(dp[p][j+h],dp[p][j]+dp[u][h]+val[i]*h*(k-h));
}
}
}
if(lef){
siz[p]=1;
dp[p][1]=0;
}
}
int main(){
int t=rd(),cas=0;
while(t--){
init_edge();
mmm(deg,0);
n=rd(),k=rd();
rep(i,1,n)
rep(j,0,k)
dp[i][j]=inf;
rep(i,1,n-1){
int a=rd(),b=rd(),v=rd();
add(a,b,v),add(b,a,v);
deg[a]++,deg[b]++;
}
int rt=1;
rep(i,1,n){
if(deg[i]>1){rt=i;break;}
}
if(n==2){
if(k==1)printf("Case #%d: %d\n",++cas,0);
else printf("Case #%d: %d\n",++cas,val[1]);
continue;
}
dfs(rt,-1);
printf("Case #%d: %lld\n",++cas,dp[rt][k]);
}
return 0;
}
标签:lengthedge,son,fa,树形,100,Factories,dp,define 来源: https://blog.csdn.net/jk_chen_acmer/article/details/100177721