APIO2010巡逻 分类讨论+树的直径

APIO2010巡逻

Solution:

① K=0:

一棵树,每条边必须经过两次,ans=2*(n-1)。

② K=1:

考虑加边后形成的环。

对于环上的边我们发现能且仅仅经过一次,非环上的边不变。

因此,ans=2*(n-1)-环长。

什么时候答案最小?

显然就是当新加入的边连向树的直径两端点时,环最长,答案也最小。

③ K=2:

讨论一下两环的位置情况:

<1>、两环不相交:那么由②可知答案继续减小,答案怎么求在下面。

<2>、两环相交:为了遍历完所有的边,那么重复的部分等价于又需要经过两次,所以答案增加。

具体答案怎么多少,怎么求???

先给出算法:把直径(长度为L1)求出来后,再把直径上的边全部取负,再求一遍直径(长度为L2),

答案就是 ans=2*(n-1)-(L1-1)-(L2-1) !!!

最巧妙的一步就是把直径给取负!

可以发现,

如果得到的新的直径 经过了原来的直径,就会对应减少相交部分的长度,对应情况<2>。否则对应情况<1>。

另:这个题还有一个很有意义的就是充分考察了对直径求法的运用:

两遍BFS(DFS)可以处理出直径长度和直径的相关信息,因此第一遍必须用这种方法求。

树形DP求直径则可以处理边权为负的情况,所以第二遍又必须用这种方法求。

Code↓:

#include <bits/stdc++.h>
#define RG register
#define IL inline
#define LL long long
#define DB double
using namespace std;

IL int gi() {
    char ch=getchar(); int x=0,q=0;
    while(ch<'0'||ch>'9') q=ch=='-'?1:q,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return q?-x:x;
}

const int N=1e5+10;
const int INF=0x3f3f3f3f;

int n,K,L1,L2,tot,head[N],fa[N],tag[N],dis[N];

struct EDGE{int next,to;}e[N<<1];
IL void make(int a,int b) {
    e[++tot]=(EDGE){head[a],b},head[a]=tot;
    e[++tot]=(EDGE){head[b],a},head[b]=tot;
}

void dfs(int x,int fx) {
    RG int i,y;
    for (i=head[x],fa[x]=fx;i;i=e[i].next)
        if ((y=e[i].to)!=fx)
            dis[y]=dis[x]+1,dfs(y,x);
}

void Tree_DP(int x,int fx) {
    RG int i,y,ver;
    for (i=head[x];i;i=e[i].next)
        if ((y=e[i].to)!=fx) {
            Tree_DP(y,x),ver=(tag[x]&&tag[y])?-1:1;
            L2=max(L2,dis[x]+dis[y]+ver);
            dis[x]=max(dis[x],dis[y]+ver);
        }
}

int main()
{
    RG int i,x,y,S,s,Max;
    n=gi(),K=gi();
    for (i=1;i<n;++i) x=gi(),y=gi(),make(x,y);
    for (i=2,S=1,Max=0,dfs(1,0);i<=n;++i)
        if (dis[i]>Max) Max=dis[i],S=i;
    dis[S]=0,dfs(S,0);
    for (i=1,s=S;i<=n;++i)
        if (dis[i]>L1) L1=dis[i],s=i;
    if (K==1) printf("%d\n",2*(n-1)-(L1-1));
    else {
        while (s) tag[s]=1,s=fa[s];
        memset(dis,0,sizeof(dis));
        Tree_DP(1,0);
        printf("%d\n",2*(n-1)-(L1-1)-(L2-1));	
    }
    return 0;
}

The End

posted @ 2019-03-28 17:29  薄荷凉了夏  阅读(150)  评论(0编辑  收藏  举报