POJ 3162 Walking Race(dfs+单调队列)

题意:对一棵树,求出从每个结点出发能到走的最长距离(每个结点最多只能经过一次),将这些距离按排成一个数组得到d[1],d[2],d[3]……d[n] ,在数列的d中求一个最长的区间,使得区间中的最大值与最小值的差不超过m。

分析:用2次dfs能求出树的直径,对于树中任意结点,到树的直径的2个端点的距离的较大者即为最长距离。得到数组d后,用2个单调队列分别维护最大与最小值,扫描d数组,同时更新答案。

View Code
#include <stdio.h>

#include <string.h>

#include <algorithm>

using namespace std;

#define N 1000001

int n,m,e;

int first[N],next[N<<1],v[N<<1],w[N<<1];

int dx[N],dy[N],d[N];

int qmin[N],qmax[N];

void init()

{

    e=0;

    memset(first+1,-1,sizeof(first[0])*n);

}

void add(int a,int b,int c)

{

    v[e]=b;

    w[e]=c;

    next[e]=first[a];

    first[a]=e++;

}

void dfs(int a,int fa,int dist,int *d)

{

    int i,b;

    for(i=first[a];~i;i=next[i])

    {

        b=v[i];

        if(b^fa)    dfs(b,a,d[b]=dist+w[i],d);

    }

}

void solve()

{

    int i,j,front1,front2,rear1,rear2;

    int ans=0;

    front1=rear1=0;

    front2=rear2=0;

    for(i=1,j=1;j<=n;j++)

    {

        while(rear1>front1 && d[qmin[rear1-1]]>=d[j]) rear1--;

        qmin[rear1++]=j;



        while(rear2>front2 && d[qmax[rear2-1]]<=d[j]) rear2--;

        qmax[rear2++]=j;



        if(d[qmax[front2]]-d[qmin[front1]]>m)

        {

            ans=max(ans,j-i);

            while(d[qmax[front2]]-d[qmin[front1]]>m)

            {

                i=min(qmin[front1],qmax[front2])+1;

                while(front1<rear1&&qmin[front1]<i)   front1++;

                while(front2<rear2&&qmax[front2]<i)   front2++;

            }

        }

    }

    ans=max(ans,j-i);

    printf("%d\n",ans);

}

int main()

{

    int i,a,b,c,x,y;

    while(~scanf("%d%d",&n,&m))

    {

        init();

        for(a=2;a<=n;a++)

        {

            scanf("%d%d",&b,&c);

            add(a,b,c);

            add(b,a,c);

        }

        dfs(1,0,dx[1]=0,dx);



        for(x=1,i=2;i<=n;i++)

        {

            if(dx[i]>dx[x]) x=i;

        }

        dfs(x,0,dx[x]=0,dx);

        for(y=1,i=2;i<=n;i++)

        {

            if(dx[i]>dx[y]) y=i;

        }

        dfs(y,0,dy[y]=0,dy);

        for(int i=1;i<=n;i++)   d[i]=max(dx[i],dy[i]);

        solve();

    }

    return 0;

}

 

你可能感兴趣的:(poj)