• POJ 3162 Walking Race(树的直径+单调队列)


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

    思路:先找出树的直径的两个端点来,那么树当中的其它节点能走的最大距离一定是到这个两个点当中的其中一个的。所以三遍bfs就可以求出来这个最远的距离,那么,这个最远的距离求出来之后再用两个单调队列来维护最大值和最小值。

    /*************************************************************************
        > File Name:            poj_3162.cpp
        > Author:               Howe_Young
        > Mail:                 1013410795@qq.com
        > Created Time:         2015年09月05日 星期六 14时00分47秒
     ************************************************************************/
    
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef long long LL;
    const int maxn = 1e6 + 10;
    int tot, head[maxn];
    struct Edge {
        int to, next, w;
    }edge[maxn * 2];
    typedef pair<int, int> pii;
    int dis1[maxn], dis2[maxn], dis[maxn];
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    void addedge(int u, int v, int w)
    {
        edge[tot].to = v;
        edge[tot].w = w;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int pos, maxx;
    bool vis[maxn];
    void bfs(int u, int *dist)//从u点开始搜索到各个点的距离,保存在dist当中
    {
        maxx = 0;
        queue<pii> Q;
        memset(vis, false, sizeof(vis));
        pii cur, nex;
        cur.first = u; cur.second = 0;
        vis[u] = true;
        dist[u] = 0;
        Q.push(cur);
        while (!Q.empty())
        {
            cur = Q.front();
            Q.pop();
            for (int i = head[cur.first]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if (vis[v]) continue;
                vis[v] = true;
                nex.first = v; nex.second = cur.second + edge[i].w;
                dist[v] = nex.second;
                if (maxx < nex.second)
                {
                    maxx = nex.second;
                    pos = v;//直径的一个端点保存在pos当中
                }
                Q.push(nex);
            }
        }
    }
    int Q_max[maxn], Q_min[maxn];
    int n, m;
    int solve()//用两个单调队列分别维护最大值和最小值
    {
        int ans = 0;
        int front1, front2, tail1, tail2, i, j;
        front1 = front2 = 1; tail1 = tail2 = 0;
        for (j = 1, i = 1; i <= n; i++)
        {
            while (tail1 >= front1 && dis[Q_max[tail1]] <= dis[i]) tail1--;
            Q_max[++tail1] = i;
    
            while (tail2 >= front2 && dis[Q_min[tail2]] >= dis[i]) tail2--;
            Q_min[++tail2] = i;
    
            if (dis[Q_max[front1]] - dis[Q_min[front2]] > m)
            {
                ans = max(ans, i - j);
                while (dis[Q_max[front1]] - dis[Q_min[front2]] > m)
                {
                    j = min(Q_max[front1], Q_min[front2]) + 1;
                    while (tail1 >= front1 && Q_max[front1] < j) front1++;
                    while (tail2 >= front2 && Q_min[front2] < j) front2++;
                }
            }
        }
        ans = max(ans, i - j);
        return ans;
    }
    int main()
    {
        while (~scanf("%d %d", &n, &m))
        {
            int v, w;
            init();
            for (int i = 1; i < n; i++)
            {
                scanf("%d %d", &v, &w);
                addedge(i + 1, v, w);
                addedge(v, i + 1, w);
            }
            bfs(1, dis1);
            bfs(pos, dis1);
            bfs(pos, dis2);
            for (int i = 1; i <= n; i++)
                dis[i] = max(dis1[i], dis2[i]);
            printf("%d
    ", solve());
        }
        return 0;
    }
  • 相关阅读:
    【1】maven来管理我的SSM项目
    mybatis从数据库中取到的date格式不是yyyy-MM-dd HH:mm:ss
    hadoop的webUI查看Live Nodes为1
    CentOS6.8系统下,ecipse下进行编辑操作,意外退出
    【5】namenode启动过程
    电脑意外重启,导致虚拟机启动失败
    第3章 路由和数据传递
    第2章 基于三层架构搭建MVC系统
    第1章 进入ASP.NET MVC世界
    第13章 集合
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4783270.html
Copyright © 2020-2023  润新知