您的位置:首页 > 其它

hdu 5148 cities 树形DP

2014-12-26 23:54 393 查看
*******************************bestcoder题解********************************
Cities
选出K个点v1,v2,...vK使得∑Ki=1∑Kj=1dis(vi,vj)最小.
考虑每条边的贡献,一条边会把树分成两部分,若在其中一部分里选择了x个点,则这条边被统计的次数为x*(K-x)*2.
那么考虑dp[u][i]表示在u的子树中选择了i个点的最小代价,有转移dp[u][i]=minKj=0(dp[u][i−j]+dp[v][j]+j∗(K−j)∗2∗wu,v),式子中u为v的父亲,wu,v表示(u,v)这条边的长度.
时间复杂度O(nK^2).

****************************************************************************


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<memory.h>
usingnamespacestd;
typedeflonglongLL;
constintINF=0x3fffffff;
constLLLINF=INF*1ll*INF;
usingnamespacestd;

#defineMAXN5005

structEdge{
intto;
intw;
intnext;
};

LLdp[MAXN][60];//dp
[k]代表第n个结点有k个结点连通
Edgee[MAXN];
inthead[MAXN];
intt;
intn,k;

//适用于正负整数
template<classT>
inlineboolscan_d(T&ret){
charc;intsgn;
if(c=getchar(),c==EOF)return0;//EOF
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret=ret*10+(c-'0');
ret*=sgn;
return1;
}

//取小值给ans
LLupdate(LL&ans,LLtemp)
{
if(ans>temp)ans=temp;
}

voiddfs(intu,intfa){
for(inti=head[u];~i;i=e[i].next){//注意~运算
if(e[i].to==fa)continue;//不再访问父亲结点
dfs(e[i].to,u);
}
for(inti=0;i<=k;i++)dp[u][i]=LINF;//LINF代表不可达
dp[u][1]=0;
for(inti=head[u];!i;i=e[i].next){//访问当前点u的所有子树
if(e[i].to==fa)continue;//不包含父亲结点
intv=e[i].to;
for(inta=k;a>=0;a--){//类似01背包
for(intb=1;a+b<=k;b++){//因为一条边把树分成两个部分,其中一部分已经访问了a个结点,则另一部分还需访问k-a个结点
if(dp[v][b]==LINF)break;//若为LINF则不可达比如,只有两个子节点,则dp[v][4]就不存在
update(dp[u][a+b],dp[u][a]+dp[v][b]+2ll*b*(k-b)*e[i].w);
}
}
}
}

//建立关于边的临街边
voidaddedge(intfrom,intto,intw)
{
e[t].to=to;
e[t].w=w;
e[t].next=head[from];
head[from]=t;
t++;
}

voidprocess()
{
intfrom,target,weight;
scan_d(n);
scan_d(k);
t=0;
memset(head,-1,sizeof(head));
for(inti=1;i<n;++i){
scan_d(from);
scan_d(target);
scan_d(weight);
addedge(from,target,weight);
addedge(target,from,weight);
}
dfs(1,-1);
LLans=LINF;
for(inti=1;i<=n;++i){
update(ans,dp[i][k]);
}
cout<<ans<<endl;
}

intmain()
{
intT;
cin>>T;
while(T--)
{
process();
}
return0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: