[SPFA]JZOJ 3086 回家

Description

moreD城的城市轨道交通建设终于全部竣工,由于前期规划周密,建成后的轨道交通网络由 2n 条地铁线路构成,组成了一个 纵 横的交通网。如下图所示,这 2n 条线路每条线路都包含 个车站,而每个车站都在一组纵横线路的交汇处。


出于建设成本的考虑,并非每个车站都能够进行站内换乘,能够进行站内换乘的地铁站共有 个,在下图中,标上方块标记的车站为换乘车站。已知地铁运行 站需要 分钟,而站内换乘需要步行 分钟。 你的最后一个作业就是算出,在不中途出站的前提下,从学校回家最快需要多少时间(等车时间忽略不计)。


 


 

 

Input

第一行有两个整数 n, m。接下去 行每行两个整数 x, y,表示第 条横向线路与第 条纵向线路的交汇站是站内换乘站。接下去一行是四个整数 x1,  y1,  x2,  y2。表示从学校回家时,在第 x1条横向线路与第 y1 条纵向线路的交汇站上车,在第 x2 条横向线路与第 y2 条纵向线路的交汇站下车。


 

Output

仅一个整数表示在合理选择线路的情况下,回家所需要的最少时间。如果无法在不出站换车的情况下回家则输出-1.


 

 

Sample Input

Sample Input 1
6 9
2 1
2 5
3 2
4 4
5 2
5 6
6 1
6 3
6 4
1 1 4 6

Sample Input 2
6 10
2 1
2 5
3 2
4 4
5 2
5 6
6 1
6 3
6 4
6 6
1 1 4 6

Sample Input 3
2 1
1 2
1 1 2 2

Sample Output

Sample Output 1
27

Sample Output 2 
26

Sample Output 3
5
 

Data Constraint

 
 

Hint

对于10%的数据m=0


对于 30%的数据,≤ 50, m ≤ 1000


对于 60%的数据,≤ 500, m ≤ 2000


对于 100%的数据,≤ 20000, m ≤ 100000

 

分析

看到换站要1单位时间就想到了网络流……的建图

我们把可以换乘的点拆成一条边就行了

跑SPFA轻松解决

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int N=2e4+10;
const int M=1e5+10;
struct Edge {
    int u,v,w,nx;
}g[10*M];
int cnt,list[2*M],d[2*M];
bool b[2*M];
struct Point {
    int x,y,id;
}a[M],s,t;
int n,m;

bool CMP1(Point a,Point b) {
    return a.x<b.x||a.x==b.x&&a.y<b.y;
}

bool CMP2(Point a,Point b) {
    return a.y<b.y||a.y==b.y&&a.x<b.x;
}

void Add(int u,int v,int w) {
    g[++cnt]=(Edge){u,v,w,list[u]};list[u]=cnt;
    g[++cnt]=(Edge){v,u,w,list[v]};list[v]=cnt;
}

void SPFA(int v0) {
    queue<int> q;
    while (!q.empty()) q.pop();
    for (int i=1;i<=2*m+4;i++) d[i]=2147483647;
    d[v0]=0;b[v0]=1;
    q.push(v0);
    while (!q.empty()) {
        int u=q.front();q.pop();
        for (int i=list[u];i;i=g[i].nx)
            if (d[g[i].v]>d[u]+g[i].w) {
                d[g[i].v]=d[u]+g[i].w;
                if (!b[g[i].v]) q.push(g[i].v);
                b[g[i].v]=1;
            }
        b[u]=0;
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i,Add(a[i].id,a[i].id+m+2,1);
    scanf("%d%d%d%d",&s.x,&s.y,&t.x,&t.y);s.id=m+1;t.id=m+2;Add(m+1,2*m+3,0);Add(m+2,2*m+4,0);a[m+1]=s;a[m+2]=t;
    sort(a+1,a+m+3,CMP1);
    for (int i=1;i<m+2;i++) if (a[i].x==a[i+1].x) Add(a[i].id,a[i+1].id,2*(a[i+1].y-a[i].y));
    sort(a+1,a+m+3,CMP2);
    for (int i=1;i<m+2;i++) if (a[i].y==a[i+1].y) Add(a[i].id+m+2,a[i+1].id+m+2,2*(a[i+1].x-a[i].x));
    SPFA(m+1);
    printf("%d\n",d[m+2]==2147483647?-1:d[m+2]);
}
View Code

 

posted @ 2019-01-24 20:57  Vagari  阅读(138)  评论(0编辑  收藏  举报