【BZOJ4152】The Captain

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4152


 

贪心+最短路吧,如果两点之间存在一个拐点,那么经过挂点一定不会比直接到达差,这个很容易想象,因此,我们应将横纵坐标分别排序,将相邻的横纵坐标之间建边。

细节也不多,本题的关键就是如何巧妙地建边,而不是建n^2条边。哦,据说题目卡了SPFA,和我又有啥关系呢。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

inline int get_num() {
    int num = 0;
    char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9')
        num = num * 10 + c - '0', c = getchar();
    return num;
}

const int maxn = 2e5 + 5, inf = 0x3f3f3f3f;

int head[maxn], eid;

struct Edge {
    int v, w, next;
} edge[4 * maxn];

inline void insert(int u, int v, int w) {
    edge[++eid].v = v;
    edge[eid].w = w;
    edge[eid].next = head[u];
    head[u] = eid;
}

inline void insert2(int u, int v, int w) {
    insert(u, v, w);
    insert(v, u, w);
}

int dist[maxn], vis[maxn];

struct node {
    int id, dist;
    node(int i, int d) : id(i), dist(d) {}
    bool operator < (const node& rhs) const {
        return dist > rhs.dist;
    }
};

priority_queue<node> q;

inline void dijkstra() {
    memset(dist, inf, sizeof(dist));
    dist[1] = 0;
    q.push(node(1, 0));
    while (!q.empty()) {
        int u = q.top().id;
        q.pop();
        if (vis[u]) continue;
        vis[u] = 1;
        for (int p = head[u]; p; p = edge[p].next) {
            int v = edge[p].v, w = edge[p].w;
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                q.push(node(v, dist[v]));
            }
        }
    }
}

struct Point {
    int id, x, y;
} point[maxn];

bool comp1(const Point& lhs, const Point& rhs) {
    return lhs.x < rhs.x;
}

bool comp2(const Point& lhs, const Point& rhs) {
    return lhs.y < rhs.y;
}

int main() {
    int n = get_num();
    for (int i = 1; i <= n; ++i)
        point[i].id = i, point[i].x = get_num(), point[i].y = get_num();
    sort(point + 1, point + n + 1, comp1);
    for (int i = 2; i <= n; ++i)
        insert2(point[i - 1].id, point[i].id, point[i].x - point[i - 1].x);
    sort(point + 1, point + n + 1, comp2);
    for (int i = 1; i <= n; ++i)
        insert2(point[i - 1].id, point[i].id, point[i].y - point[i - 1].y);
    dijkstra();
    printf("%d", dist[n]);
    return 0;
}
AC代码

 

posted @ 2018-11-04 07:43  Mr^Kevin  阅读(150)  评论(0编辑  收藏  举报