对最外层所有叶子编号(编号都为 (1)),然后把他们删去,然后给倒数第二层叶子编号(编号都为 (2))。以此类推。
对于每一种编号考虑,由于一条路径最多只能覆盖两个编号相同的节点,所以最后答案为 (sumlimits_{i=1}^{k}max(2 imes L,sum[i]))。其中 (k) 为叶子总层数,(sum[i]) 表示一种编号的点有多少个。
显然这个式子是答案的上界,至于为什么能取到也可以证明(但我不会,所以说这是结论题)。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=1000009;
int n,head[N],cnt,deg[N],L,del[N],ans;
queue <int> q;
struct Edge
{
int nxt,to;
}g[N*2];
void add(int from,int to)
{
g[++cnt].nxt=head[from];
g[cnt].to=to;
head[from]=cnt;
}
void init()
{
scanf("%d %d",&n,&L);
for (int i=1,x,y;i<n;i++)
scanf("%d %d",&x,&y),
add(x,y),add(y,x),deg[x]++,deg[y]++;
}
void work()
{
for (int i=1;i<=n;i++)
if(deg[i]==1)
q.push(i),del[i]=1;
int last=q.size();
ans+=min(2*L,(int)q.size());
while(!q.empty())
{
int x=q.front();q.pop();
last--,del[x]=1;
for (int i=head[x];i;i=g[i].nxt)
{
int v=g[i].to;
if(del[v]) continue;
deg[v]--;
if(deg[v]==1)
q.push(v);
}
if(!last) last=q.size(),ans+=min(2*L,(int)q.size());
}
printf("%d
",ans);
}
int main()
{
init();
work();
return 0;
}