从前有棵树。
找出K个点A1,A2,…,Ak。
使得∑dis(AiAi+1),(1<=i<=K-1)最小。
标签:font class etc while -- soft cstring tree ext
题解:用f[i][j][0/1/2]表示在i的子树中,选择j个点,且包含0/1/2个路径的端点,的最小总长度。然后跑树形背包即可。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n,m,cnt,ans; int f[3010][3010][3],to[6010],next[6010],val[6010],head[3010],siz[3010]; inline void add(int a,int b,int c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } void dfs(int x,int fa) { int i,j,k,l,h,y; f[x][1][0]=f[x][1][1]=f[x][1][2]=0,siz[x]=1; for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) { dfs(to[i],x),y=to[i]; for(k=min(siz[x],m);k;k--) for(l=0;l<=2;l++) for(j=min(siz[y],m-k);j;j--) for(h=0;h<=2-l;h++) f[x][k+j][l+h]=min(f[x][k+j][l+h],f[x][k][l]+f[y][j][h]+val[i]+val[i]*(h!=1)); siz[x]+=siz[y]; } ans=min(ans,f[x][m][2]); } int main() { n=rd(),m=rd(); int i,a,b,c; memset(head,-1,sizeof(head)); for(i=1;i<n;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c); memset(f,0x3f,sizeof(f)); ans=1<<30; dfs(1,0); printf("%d",ans); return 0; }
标签:font class etc while -- soft cstring tree ext
原文地址:http://www.cnblogs.com/CQzhangyu/p/7560521.html