 /**//*
题意:给出一棵树,求一条最长为L的路,使得所有节点到这条路的距离(选离最近的点)之和最小
N<=10^4,L<=100
树DP
dp[u,L]表示以u为根的子树,最长为L的路的代价(即距离之和)
其中u为其中的一个点,以u为根的子树是指在所有节点以0为根的前提下,u的这颗子树(即只有部分点)
sumD[u]表示u的子树所有点到u的距离之和
sum[u]表示u的子树的节点个数

这个dp[u,L]的维护:
dp[u,L] = min{ dp[u,L], dp[u,L-1], dp[v][i-1]+sumD[u]-sumD[v]-sum[v] } v是u的一个儿子
由于dp[u,L]表示的是长度不超过L的,所以需要跟dp[u,L-1]比较

定义长度不超过L,可以使整个复杂度为O(NL)
定义长度为L的话,整个复杂度会变为O(NLL)
以上是第一次dfs得到的值,这样子得到的是以0为根的答案ans[0]
当然可以以其他点为根,这时需要第二次dfs来调整整棵树的根

ans[u] =
N-sum[u] + sumD[p]-sum[u] //调整其他点到根的距离
+ dp[v1,a] - sumD[v1] - sum[v1] //选择两个点来作为路径,也可以是一个点的
+ dp[v2,b] - sumD[v2] - sum[v2]

用tmp[l]记录目前的 min{dp[v,l] - sumD[v] - sum[v]} 即可

*/
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;

const int MAXN = 10010;
const int INF = 1000000000;

 inline int min(int a,int b) {return a<b?a:b;}

struct Node
  {
int v;
Node *next;
};

int dp[MAXN][110];
int N,L;
int sumD[MAXN],sum[MAXN];
int ans[MAXN];

Node *E[MAXN],nodes[MAXN*2],*pE;

void init()
  {
pE=nodes;
for(int i=0;i<N;i++)
E[i]=0;
}

void add(int a,int b)
  {
pE->v=b;
pE->next=E[a];
E[a]=pE++;
}

void dfs1(int u,int p)
  {
fill(dp[u],dp[u]+L+1,INF);
sum[u]=1;
sumD[u]=0;
for(Node *it=E[u];it;it=it->next)
 {
int v=it->v;
if(v==p)continue;
dfs1(v,u);
sumD[u]+=sumD[v]+sum[v];
sum[u]+=sum[v];
}
dp[u][0]=sumD[u];
for(Node *it=E[u];it;it=it->next)
 {
int v=it->v;
if(v==p)continue;
for(int i=1;i<=L;i++)
 {
dp[u][i]=min(dp[u][i],dp[v][i-1]+sumD[u]-sumD[v]-sum[v]);
dp[u][i]=min(dp[u][i],dp[u][i-1]);
}
}
}

void dfs2(int u,int p)
  {
if(u==0)ans[u]=sumD[0];
else ans[u]=N-sum[u] + sumD[p]-sum[u];//
int tmp[110];//tmp[i]表示目前长度不超过i的 dp[v][i]-sumD[v]-sum[v] 的最小值
int Min = INF;
fill(tmp,tmp+L+1,INF);
for(Node *it=E[u];it;it=it->next)
 {
int v=it->v;
if(v==p)continue;
if(L>=2)//一条a + 一条b组成
 {
for(int a=0;a<=L-2;a++)
//如果定义长度为L的话,这里需要再for(b=0;a+b<=L-2;b++)
//而定义长度不超过L的话,那个tmp[b=L-2-a]就是这个for的最优值了
//所以复杂度降为O(NL)
 {
int b=L-2-a;
Min=min(Min,tmp[b]+dp[v][a]-sumD[v]-sum[v]);
}
}
for(int a=0;a<=L;a++)//更新tmp[]
 {
tmp[a]=min(tmp[a],dp[v][a]-sumD[v]-sum[v]);
if(a)tmp[a]=min(tmp[a],tmp[a-1]);// tmp[i]表示最多用长度为i的 所以可以=tmp[a-1]
}
}
Min = min(Min,tmp[L-1]);//也可以只有1条的
sumD[u]=ans[u];
ans[u]+=Min;
for(Node *it=E[u];it;it=it->next)
 {
int v=it->v;
if(v==p)continue;
dfs2(v,u);
}
}
int main()
  {
// freopen("in", "r", stdin);
//freopen("out", "w", stdout);

while(scanf("%d%d",&N,&L),N||L)
 {
 if(N==1) {puts("0");continue;}
init();
int a,b;
for(int i=1;i<N;i++)
 {
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs1(0,0);
dfs2(0,0);
printf("%d\n",*min_element(ans,ans+N));
}
return 0;
}

|
|
常用链接
随笔分类
Links
搜索
最新评论

|
|