NOIP提高组【JZOJ4805.】跟踪

来源:互联网 发布:大华行知实验幼儿园 编辑:程序博客网 时间:2024/06/06 19:11

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

这道题其实很简单。我们先将s视为树根,遍历一下,求出每个点作以他为根的子树的最大深度。然后我们将s到p和s到q的路径上的点都走一遍,求出不包括当前点x不包括s到p和s到q的路径上的点时以他为根的子树的最大深度,求一遍答案即可。

代码

#include<iostream>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=400005;int first[maxn],last[maxn],next[maxn],v[maxn],deep[maxn],mx[maxn],fa[maxn];int n,m,i,t,j,k,l,x,y,s,z,p,q,num,ln,fa2,fa1,ans,road[maxn],road1[maxn],num1;bool bz[maxn];void lian(int x,int y){    last[++num]=y;next[num]=first[x];first[x]=num;}void bfs(){    int i=0,j=1,t,k,l,x;    v[1]=s;bz[s]=true;deep[s]=0;    while (i<j){        x=v[++i];        for (t=first[x];t;t=next[t]){            if (bz[last[t]]) continue;            v[++j]=last[t],fa[v[j]]=x;deep[v[j]]=deep[x]+1;bz[last[t]]=true;        }    }    for (i=n;i>=1;i--)        mx[fa[v[i]]]=max(mx[fa[v[i]]]+1,mx[v[i]]);}int main(){//  freopen("track.in","r",stdin);freopen("track.out","w",stdout);    scanf("%d%d%d%d",&n,&s,&p,&q);    for (i=1;i<n;i++)        scanf("%d%d",&x,&y),lian(x,y),lian(y,x);        bfs();fa2=p;fa1=q;num=0;memset(bz,0,sizeof(bz));    while (fa2!=s) bz[fa2]=true,road[++num]=fa2,fa2=fa[fa2];    while (fa1!=s) bz[fa1]=true,road1[++num1]=fa1,fa1=fa[fa1];    mx[s]=1;    bz[s]=true;mx[s]=0;    for (t=first[s];t;t=next[t])        if (!bz[last[t]]) mx[s]=max(mx[last[t]]+1,mx[s]);    if (mx[s]>=min(deep[p],deep[q])) ans=3*min(deep[p],deep[q]);    else{        t=mx[s]+min(deep[p],deep[q]);        k=t/2;        ans=k*3;        if (t%2) ans+=2;    }    l=0;x=deep[p],y=deep[q];    for (i=num;i>=1;i--){        x-=3;        y--;z=road[i];mx[z]=0;        if (x<=0 || y<=0){            if (x!=-2)ans=max(ans,l+2);            else ans=max(ans,l+1);break;            }l+=3;        for (t=first[z];t;t=next[t])            if (!bz[last[t]])mx[z]=max(mx[last[t]]+1,mx[s]);        if (mx[z]>=min(x,y)) ans=max(ans,l+3*min(x,y));        else{            t=mx[z]+min(x,y);            k=t/2;k*=3;            if (t%2) k+=2;            ans=max(ans,l+k);        }    }    l=0;x=deep[p],y=deep[q];    for (i=num1;i>=1;i--){        x--;        y-=3;z=road1[i];mx[z]=0;        if (x<=0 || y<=0){            if (y!=-2)ans=max(ans,l+2);            else ans=max(ans,l+1);break;            }l+=3;        for (t=first[z];t;t=next[t])            if (!bz[last[t]])mx[z]=max(mx[last[t]]+1,mx[s]);        if (mx[z]>=min(x,y)) ans=max(ans,l+3*min(x,y));        else{            t=mx[z]+min(x,y);            k=t/2;k*=3;            if (t%2) k+=2;            ans=max(ans,l+k);        }    }    printf("%d\n",ans);}
3 0
原创粉丝点击