[APIO2010] 巡逻

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
int n,k,x,y,to[200005],next[200005],pp[200005],pan[200005],dd[200005],dep[200005],f[200005];
int len,dang,ans,p,wang[200005],v[200005];
void dfs1(int k)
{
    pan[k]=1;dd[k]=dep[k];
    int pu=pp[k],m1=dep[k],m2=dep[k];
    while (pu>0)
    {
        if (pan[to[pu]]==0)
        {
            dep[to[pu]]=dep[k]+1;dfs1(to[pu]);
            dd[k]=max(dd[k],dd[to[pu]]);
            if (dd[to[pu]]>m1){m2=m1;m1=dd[to[pu]];}
            else if (dd[to[pu]]>m2)m2=dd[to[pu]];
        }
        pu=next[pu];
    }
    if (m1+m2-dep[k]-dep[k]>=len){len=m1+m2-dep[k]-dep[k];dang=k;}
}
void dfs2(int k)
{
    pan[k]=0;dd[k]=dep[k];
    int pu=pp[k],m1=0,m2=0;
    while (pu>0)
    {
        if (pan[to[pu]]==1)
        {
            dep[to[pu]]=dep[k]+1;dfs2(to[pu]);
            if (dd[to[pu]]>dd[k]){dd[k]=dd[to[pu]];wang[k]=to[pu];}
            if (dd[to[pu]]>dd[m1]){m2=m1;m1=to[pu];}
            else if (dd[to[pu]]>dd[m2])m2=to[pu];
        }
        pu=next[pu];
    }
    if (k==dang)
    {
        while (m1>0){v[m1]=-1;m1=wang[m1];}
        while (m2>0){v[m2]=-1;m2=wang[m2];}
    }
}
void dfs3(int k)
{
    pan[k]=1;f[k]=0;
    int pu=pp[k],m1=0,m2=0;
    while (pu>0)
    {
        if (pan[to[pu]]==0)
        {
            dfs3(to[pu]);
            f[k]=max(f[k],f[to[pu]]+v[to[pu]]);
            if (f[to[pu]]+v[to[pu]]>m1){m2=m1;m1=f[to[pu]]+v[to[pu]];}
            else if (f[to[pu]]+v[to[pu]]>m2){m2=f[to[pu]]+v[to[pu]];}
        }
        pu=next[pu];
    }
    if (m1+m2>len)len=m1+m2;
}
int main()
{
    cin>>n>>k;ans=2*(n-1);
    for (int i=1;i<n;i++)
    {
        scanf("%d %d",&x,&y);
        p++;to[p]=x;next[p]=pp[y];pp[y]=p;
        p++;to[p]=y;next[p]=pp[x];pp[x]=p;
    }    
    dep[1]=1;
    dfs1(1);
    ans-=len-1;dep[dang]=1;
    if (k==1){cout<<ans;return 0;}
    for (int i=1;i<=n;i++)v[i]=1;
    dfs2(dang);
    len=0;
    dfs3(dang);
    ans-=len-1;
    cout<<ans;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值