• bzoj4152 [AMPPZ2014]The Captain


    4152: [AMPPZ2014]The Captain

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 1293  Solved: 502
    [Submit][Status][Discuss]

    Description

    给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。

    Input

    第一行包含一个正整数n(2<=n<=200000),表示点数。
    接下来n行,每行包含两个整数x[i],y[i](0<=x[i],y[i]<=10^9),依次表示每个点的坐标。
     
     

    Output

    一个整数,即最小费用。

    Sample Input

    5
    2 2
    1 1
    4 5
    7 1
    6 7

    Sample Output

    2

    HINT

     

    Source

    分析:这道题最关键的一点就是如何建图,如果每两个点都连一条边,那么空间会直接炸掉,考虑哪些边不用连.如果两个点之间有中间点的话,一定是走中间点的!这个可以非常容易证明,那么我们先按照x排序,再按照y排序,只在相邻点之间连边就好了.
          不过这道题卡spfa,用dijkstra就是稳定的O(nlogn)了,不会超时.
    如果建边是最短路问题的考点,那么先考虑能不能有一个只进不出和一个只出不进的中间点,如果不行,看建边的点是不是区间的形式,如果还不行,就要分析问题,看能不能删掉某些边.
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    using namespace std;
    
    const int maxn = 200010;
    const long long inf = 1000000000000000;
    
    struct node
    {
        int x,y,id;
    }e[200010]; 
    
    struct node2
    {
        int x;
        long long len;
    };
    
    bool operator < (node2 a,node2 b)
    {
        return a.len > b.len;
    }
    
    int n,head[maxn],to[maxn * 4],nextt[maxn * 4],tot = 1,w[maxn * 4],vis[maxn * 4];
    priority_queue <node2> q;
    long long d[maxn];
    
    bool cmp1(node a,node b)
    {
        return a.x < b.x;
    }
    
    bool cmp2(node a,node b)
    {
        return a.y < b.y;
    }
    
    void add(int x,int y,int z)
    {
        w[tot] = z;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void dijkstra()
    {
        for (int i = 1; i <= n; i++)
        d[i] = inf;
        d[1] = 0;
        node2 temp;
        temp.len = 0;
        temp.x = 1;
        q.push(temp);
        while (!q.empty())
        {
            while (!q.empty() && vis[q.top().x])
            q.pop();
            if (q.empty())
            return;
            node2 u = q.top();
            q.pop();
            int x = u.x;
            long long len = u.len;
            vis[x] = 1;
            for (int i = head[x]; i;i = nextt[i])
            {
                int v = to[i];
                if (d[v] > d[x] + w[i])
                {
                    d[v] = d[x] + w[i];
                    node2 temp;
                    temp.x = v;
                    temp.len = d[v];
                    q.push(temp);
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i = 1; i <= n; i++)
        {
        scanf("%d%d",&e[i].x,&e[i].y);
        e[i].id = i;
        }
        sort(e + 1,e + 1 + n,cmp1);
        for (int i = 1; i < n; i++)
        {
        int t = min(abs(e[i].x - e[i + 1].x),abs(e[i].y - e[i + 1].y));
        add(e[i].id,e[i + 1].id,t);
        add(e[i+1].id,e[i].id,t);
        }
        sort(e + 1,e + 1 + n,cmp2);
        for (int i = 1; i < n; i++)
        {
        int t = min(abs(e[i].x - e[i + 1].x),abs(e[i].y - e[i + 1].y));
        add(e[i].id,e[i + 1].id,t);
        add(e[i+1].id,e[i].id,t);
        }
        dijkstra();
        printf("%lld
    ",d[n]);
    
        return 0;
    }
  • 相关阅读:
    HDU-ACM“菜鸟先飞”冬训系列赛——第9场
    HDU3092:Least common multiple(素数筛选+完全背包)
    HDU1452:Happy 2004(积性函数)(因子和)
    HDU-ACM“菜鸟先飞”冬训系列赛——第8场(1004)
    Codeforces Round #395 (Div. 2)
    一些算法技巧整理(添加中)
    poj 1852 Ants
    hdu 1587 Flowers
    hdu 1563 Find your present!
    hdu 1570 AC
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7515111.html
Copyright © 2020-2023  润新知