点击这里查看原题
这个题k只有两种情况,因此可以分类来考虑。
k=1时显然将树的直径两端连起来可以省下的路径最多。
k=2时,再建一条路一定会形成一个新的环,因为建的路必须走,所以环上每一条边都需要走一次。环上的是树的直径的边越多,则损失越大(因为重复走了),环上的不是树的直径的边越多,则节省的路径越多。因此需要将树的直径上的每一条边权变为-1,然后再做一次树的直径。
/*
User:Small
Language:C++
Problem No.:1912
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=1e5+5;
int n,m,ans,fir[M],tot=1,s,d,son1[M],son2[M];
struct edge{
int v,w,nex;
}e[M<<2];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,fir[u]};
fir[u]=tot;
}
int dfs(int u,int fa){
int max1=0,max2=0;
for(int i=fir[u];i;i=e[i].nex){
int v=e[i].v;
if(v==fa) continue;
int nowh=dfs(v,u)+e[i].w;
if(nowh>max1){
max2=max1;
son2[u]=son1[u];
son1[u]=i;
max1=nowh;
}
else if(nowh>max2){
son2[u]=i;
max2=nowh;
}
}
if(max1+max2>d){
d=max1+max2;
s=u;
}
return max1;
}
int main(){
freopen("data.in","r",stdin);//
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v,1);
add(v,u,1);
}
ans=(n-1)<<1;
dfs(1,0);
ans-=d-1;
if(m>1){
for(int i=son1[s];i;i=son1[e[i].v]) e[i].w=e[i^1].w=-1;
for(int i=son2[s];i;i=son1[e[i].v]) e[i].w=e[i^1].w=-1;
memset(son1,0,sizeof(son1));
memset(son2,0,sizeof(son2));
d=0;
dfs(1,0);
ans-=d-1;
}
printf("%d\n",ans);
return 0;
}