zoukankan      html  css  js  c++  java
  • D:Returning Home-Codeforces Round #675 (Div. 2)

    D:Returning Home-Codeforces Round #675 (Div. 2)

    Problem:

    Yura has been walking for some time already and is planning to return home. He needs to get home as fast as possible. To do this, Yura can use the instant-movement locations around the city.

    Let's represent the city as an area of (n×n) square blocks. Yura needs to move from the block with coordinates ((sx,sy)) to the block with coordinates ((fx,fy)). In one minute Yura can move to any neighboring by side block; in other words, he can move in four directions. Also, there are mm instant-movement locations in the city. Their coordinates are known to you and Yura. Yura can move to an instant-movement location in no time if he is located in a block with the same coordinate (x) or with the same coordinate (y) as the location.

    Help Yura to find the smallest time needed to get home.

    Input:

    The first line contains two integers nn and mm — the size of the city and the number of instant-movement locations ((1≤n≤10^9, 0≤m≤10^5)).

    The next line contains four integers (sx,sy,fx,fy) — the coordinates of Yura's initial position and the coordinates of his home ((1≤sx,sy,fx,fy≤n)).

    Each of the next mm lines contains two integers (xi,yi) — coordinates of the (i)-th instant-movement location ((1≤xi,yi≤n)).

    Output:

    In the only line print the minimum time required to get home.

    Examples:

    input

    5 3
    1 1 5 5
    1 2
    4 1
    3 3
    

    output

    5
    

    input

    84 5
    67 59 41 2
    39 56
    7 2
    15 3
    74 18
    22 7
    

    output

    42
    
    Solution:

    因为可以借助location走捷径,所以我们将所有location位置记录后构造无向图,因为任意两个location都是可以互相到达的,所以这里有(m*(m-1)/2)条边,由于m最大为(10^5),显然是无法存下这么大的图的,但是经过分析我们可以发现,假设存在两个点(l(x_1,y_1),r(x_2,y_2)),两点距离为(min(abs(x_1-y_1),abs(x_2-y_2))),如果存在第三个点(k(x_3,y_3))且满足(x1 leq x_3 leq x_2),则有(dis[x_1,x_2] = dis[x_1,x_3] + dis[x_3, x_2]),因此只需要建立(edge[x_1,x_3] 和 edge[x_2,x_3]),考虑(x,y)两个方向,构造图时只需要将所有点按照(x)(y)的坐标排序之后建边即可,构造图之后,在构造图上运行最短路算法,对于起点计算(sx,sy)到每个点的距离,并进行最短路算法,之后计算最短路径加上该点到(fx,fy)的距离取其中的最小值即为答案。

    Code:
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 811111;
    const int inf = 0x3fffff;
    
    typedef long long ll;
    
    struct ad{
        int x, y, a;
        ad(int i, int j, int k) : x(i), y(j), a(k) {}
        ad() : x(0), y(0), a(0) {}
    }loc[maxn];
    
    bool cmp1(ad l, ad r) {
        if(l.x == r.x) return l.y < r.y;
        return l.x < r.x;
    }
    
    bool cmp2(ad l, ad r) {
        if(l.y == r.y) return l.x < r.x;
        return l.y < r.y;
    }
    
    ll first[maxn], nxt[maxn], cnt, v[maxn], w[maxn];
    pair<int, int> poc[maxn];
    ll dis[maxn];
    
    void add(int x, int y, int d) {
        cnt++;
        v[cnt] = y; w[cnt] = d;
        nxt[cnt] = first[x]; first[x] = cnt;
        return;
    }
    
    int main()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int n, m, sx, sy, fx, fy;
        cin >> n >> m >> sx >> sy >> fx >> fy;
        for(int i = 1; i <= m; ++i) {
            int x, y;
            cin >> x >> y;
            poc[i] = make_pair(x, y);
            loc[i] = ad(x, y, i);
        }
        memset(first, -1, sizeof(first));
        memset(nxt, -1, sizeof(nxt));
        cnt = 0;
        sort(loc + 1, loc + 1 + m, cmp1);
        for(int i = 2; i <= m; ++i) {
            ad la = loc[i - 1];
            int ds = min(abs(loc[i].x - la.x), abs(loc[i].y - la.y));
            add(loc[i].a, la.a, ds);
            add(la.a, loc[i].a, ds);
        }
        sort(loc + 1, loc + 1 + m, cmp2);
        for(int i = 2; i <= m; ++i) {
            ad la = loc[i - 1];
            int ds = min(abs(loc[i].x - la.x), abs(loc[i].y - la.y));
            add(loc[i].a, la.a, ds);
            add(la.a, loc[i].a, ds);
        }
        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> box;
        for(int i = 1; i <= m; ++i) {
            dis[i] = min(abs(sx - poc[i].first), abs(sy - poc[i].second));
            box.push(make_pair(dis[i], i));
        }
        while(!box.empty()) {
            int wd, x;
            wd = box.top().first; x = box.top().second;
            box.pop();
            if(wd != dis[x]) continue;
            for(int i = first[x]; i != -1; i = nxt[i]) {
                int y = v[i];
                int c = w[i];
                if(dis[y] > wd + c) {
                    dis[y] = wd + c;
                    box.push(make_pair(dis[y], y));
                }
            }
        }
        ll ans = abs(sx - fx) + abs(sy - fy);
        for(int i = 1; i <= m; ++i) {
            ans = min(ans, dis[i] + abs(poc[i].first - fx) + abs(poc[i].second - fy));
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    B1001 害死人不偿命的(3n+1)猜想 (15 分)
    A1050 String Subtraction (20 分)
    A1041 Be Unique (20 分)
    B1047 编程团体赛 (20 分)
    B1043 输出PATest (20 分)
    B1042 字符统计 (20 分)
    B1038 统计同成绩学生 (20 分)
    VB计算符号
    vs2008写代码的时候不能输入中文,sogou和google输入法都没有用
    如何彻底关闭Windows7自动更新
  • 原文地址:https://www.cnblogs.com/LeafLove/p/13786212.html
Copyright © 2011-2022 走看看