/* 返回顶部 */

Luogu P3831 [SHOI2012]回家的路

传送

分层最短路。

可以发现,需要做出选择的地方只有地铁站,所以点集就是所有地铁站。

所有相同x坐标地铁站之间纵向连边,点编号1~n,y相同地铁站之间纵向连边,编号n+1~2n,

边权为x或y坐标差值*2。

在每个地铁站可以选择换乘或者不换乘,如果换乘,花费为1,坐标由i变成i+n(或i-n)。

所以,在每个地铁站i与i+n之间连双向边,边权为1.

跑最短路即可w

代码如下

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 1e7;
const int INF = 0x3f3f3f3f;
int n,m,s,t;
int head[maxn],to[maxn],nxt[maxn],val[maxn];
int dis[maxn],cnt;
bool vis[maxn];

struct node {
    int id,x,y;
} a[maxn];

bool cmpx(node A,node B) {
    return A.x < B.x || ((A.x == B.x) && A.y < B.y);
}

bool cmpy(node A,node B) {
    return A.y < B.y || ((A.y == B.y) && A.x < B.x);
}

void add(int x,int y,int z) {
    to[++cnt] = y;
    nxt[cnt] = head[x];
    head[x] = cnt;
    val[cnt] = z;
}

void init() {
    for(int i = 0; i <= n+n; i++)
        dis[i] = INF;
}

void dijkstra(int s) {
    init();
    priority_queue < pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
    dis[s] = 0;
    q.push(make_pair(0,s));
    while(!q.empty()) {
        int u = q.top().second;
        q.pop();
        if(vis[u])continue;
        vis[u] = true;
        for(int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if(dis[u] + val[i] < dis[v]) {
                dis[v] = dis[u] + val[i];
                q.push(make_pair(dis[v],v));
            }
        }
    }
}

int main() {
    scanf("%d%d",&n,&m);
    n = m+2;
    s = n-1,t = n;
    for(int i = 1; i <= n; i++) {
        scanf("%d%d",&a[i].x,&a[i].y);
        a[i].id = i;
    }
    add(s,s+n,0);
    add(s+n,s,0);
    add(t,t+n,0);
    add(t+n,t,0);
    for(int i = 1; i <= n-2; i++) {
        add(i,i+n,1);
        add(i+n,i,1);
    }
    sort(a+1,a+n+1,cmpx);
    for(int i = 1; i < n; i++) {
        if(a[i].x != a[i+1].x)continue;
        add(a[i].id,a[i+1].id,(a[i+1].y-a[i].y)*2);
        add(a[i+1].id,a[i].id,(a[i+1].y-a[i].y)*2);
    }
    sort(a+1,a+n+1,cmpy);
    for(int i = 1; i < n; i++) {
        if(a[i].y != a[i+1].y)continue;
        add(a[i].id+n,a[i+1].id+n,(a[i+1].x-a[i].x)*2);
        add(a[i+1].id+n,a[i].id+n,(a[i+1].x-a[i].x)*2);
    }
    dijkstra(s);
    printf("%d\0",dis[t]);
    return 0;
}
View Code

 

posted @ 2019-05-22 14:55  Mogeko  阅读(187)  评论(0编辑  收藏  举报