【树形DP+单调队列】POJ 3162 Walking Race

通道:http://poj.org/problem?id=3162

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

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

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1e6+5;
struct Edge
{
    int v,wei,pre;
    Edge(){}
    Edge(int a,int b,int c){v=a;pre=b;wei=c;}
}edge[N*2];

int head[N],tot,n,m;
int dx[N],dy[N],d[N];
int qmin[N],qmax[N];

void addEdge(int u,int v,int wei)
{
    edge[tot]=Edge(v,head[u],wei);
    head[u]=tot++;
}
void dfs(int u,int fa,int dis,int *d)
{
    for(int i=head[u];i!=-1;i=edge[i].pre)
    {
        int v=edge[i].v,wei=edge[i].wei;
        if(v!=fa) dfs(v,u,d[v]=dis+wei,d);
    }
}
void solve()
{
    int ans=0,i,j,front1,front2,rear1,rear2;
    front1=rear1=0;
    front2=rear2=0;

    for(i=1,j=1;j<=n;j++)
    {
        while(rear1>front1&&d[qmax[rear1-1]]<=d[j]) rear1--;
        qmax[rear1++]=j;

        while(rear2>front2&&d[qmin[rear2-1]]>=d[j]) rear2--;
        qmin[rear2++]=j;

        if(d[qmax[front1]]-d[qmin[front2]]>m)
        {
            ans=max(ans,j-i);
            while(d[qmax[front1]]-d[qmin[front2]]>m)
            {
                i=min(qmax[front1],qmin[front2])+1;
                while(rear1>front1&&qmax[front1]<i) front1++;
                while(rear2>front2&&qmin[front2]<i) front2++;
            }
        }
    }
    ans=max(ans,j-i);
    printf("%d\n",ans);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tot=0;
        memset(head,-1,sizeof(head));

        int x,y,i;
        for(int i=2;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            addEdge(i,x,y);
            addEdge(x,i,y);
        }
        dfs(1,0,d[1]=0,d);
        for(x=1,i=2;i<=n;i++)
            if(d[i]>d[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;
}
View Code

 

posted @ 2014-11-03 19:29  mithrilhan  阅读(205)  评论(0编辑  收藏  举报