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;
}

 

posted @ 2012-09-20 16:58  BeatLJ  阅读(698)  评论(0编辑  收藏  举报