让你在一颗树上加1/2条边,从1点开始走,新形成的图每个边经过至少一次需要走几步
(1)如果不能加边,考虑dfs这颗树,很明显是2*(n-1)(每个边都需要走两遍)
(2)如果可以加一条边,加了改边之后形成环,改环上的边只需要走一次即可,贪心的想我们肯定加在直径上
(3)如果可以加两条边,这时候如果加了改边形成的环和上一个环有重叠,为了经过新加的这条边,我们需要把两环重叠的部分再遍历一次(即旧环中的边对新直径的贡献变成-1)。
(4)因为需要获得第一次直径的路径,应该使用两次搜索寻找,这里使用BFS
(5)第二次寻找直径出现负权,需要使用树形DP求直径
int head[MX],tot;
struct IN{int v,nxt,w;}edge[MX<<1];
void add(int u,int v,int w)
{
edge[tot].v=v;edge[tot].w=w;edge[tot].nxt=head[u];
head[u]=tot++;
}
int n,k,s,e;
int dis[MX],vis[MX];
int fa[MX];//用于找环
void bfs(int st)
{
memset(vis,0,sizeof(vis));
fa[st]=-1;
queue<int>q;
q.push(st);
dis[st]=0,vis[st]=1;
while(q.size())
{
int x=q.front();q.pop();
for(int i=head[x];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(vis[v]) continue;
fa[v]=i;
dis[v]=dis[x]+edge[i].w,vis[v]=1;
q.push(v);
}
}
s=e=st;
rpp(i,n) if(dis[i]>dis[e]) e=i;
}
int dp[MX],ans;
void dfs(int x,int fx)
{
for(int i=head[x];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(v==fx) continue;
dfs(v,x);
ans=max(ans,dp[x]+edge[i].w+dp[v]);
dp[x]=max(dp[x],dp[v]+edge[i].w);
}
}
inline int solve()
{
memset(head,-1,sizeof(head));
cin>>n>>k;
rpp(i,n-1)
{
int x,y;cin>>x>>y;
add(x,y,1);add(y,x,1);
}
bfs(1);bfs(e);
if(k==1) return 2*(n-1)-dis[e]+1;
for(int p=e;p!=s;p=edge[fa[p]^1].v)
edge[fa[p]].w=edge[fa[p]^1].w=-1; //依次更改边权
dfs(1,0);
return 2*(n-1)-dis[e]+1-ans+1;
}
signed main()
{
cout<<solve()<<endl;
stop;
return 0;
}