zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    TCP/IP断网仍然显示连通状态禁止“媒体感知”
    ASP.NET页面优化,提高载入速度方法大全
    国家气象局提供
    datatable&list<T>
    windows mobile C# net3.5 如何捕捉Arrow的CheckBox的KeyDown事件?
    hhclass 类 RAPI OpenNETCF.Desktop.Communication.DLL相关下载
    string和stringBuilder区别
    windows mobile全屏设置笔记
    CSS浮动(float,clear)通俗讲解
    js图片延时加载(jquery特效)
  • 原文地址:https://www.cnblogs.com/algorithms/p/2695496.html
Copyright © 2011-2022 走看看