[spfa] Jzoj P3086 回家

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
 

Hint

对于10%的数据m=0


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


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


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

题解

  • 题目大意:给定一个n*n的图,有n个可以转向的交点(横纵变化),每次转向需要1的代价,每走一个站需要2的代价,问从起点到终点的最小代价
  • 显然,我们可以对于一个点拆成两个点(横纵),然后对于每个转向的点的横纵相连,代价为1
  • 同行同列相连,代价为距离*2,起点和终点横纵转换可以不用代价,因为可以起点可以任意开始,终点也可以从上下到达
  • 建完图就可以直接跑spfa(不怕被卡的话)

代码

 1 #include <cstdio>
 2 #include <queue>
 3 #include <algorithm>
 4 #define inf 0x7fffffff
 5 #define N 200010
 6 using namespace std;
 7 struct node { int to,from,v; }E[N*4];
 8 struct edge { int x,y,d; }e[N];
 9 int n,m,cnt,head[N*4],dis[N],vis[N];
10 queue<int> Q;
11 bool cmp(edge a,edge b) { return (a.x==b.x)?a.y<b.y:a.x<b.x; }
12 bool CMP(edge a,edge b) { return (a.y==b.y)?a.x<b.x:a.y<b.y; }
13 void insert(int x,int y,int v) 
14 { 
15     E[++cnt].to=y,E[cnt].from=head[x],E[cnt].v=v,head[x]=cnt; 
16     E[++cnt].to=x,E[cnt].from=head[y],E[cnt].v=v,head[y]=cnt; 
17 }
18 int spfa()
19 {
20     for (int i=1;i<=(m+2)*2;i++) dis[i]=inf;
21     vis[m+1]=1,dis[m+1]=0,Q.push(m+1);
22     while (!Q.empty())
23     {
24         int u=Q.front(); Q.pop(),vis[u]=0;
25         for (int i=head[u];i;i=E[i].from)
26             if (dis[E[i].to]>dis[u]+E[i].v)
27             {
28                 dis[E[i].to]=dis[u]+E[i].v;
29                 if (!vis[E[i].to]) vis[E[i].to]=1,Q.push(E[i].to);
30             }
31     }
32     return dis[m+2]==inf?-1:dis[m+2];
33 }
34 int main()
35 {
36     scanf("%d%d",&n,&m);
37     for (int i=1;i<=m+2;i++) scanf("%d%d",&e[i].x,&e[i].y),e[i].d=i;
38     sort(e+1,e+m+2+1,cmp);
39     for (int i=1;i<m+2;i++) if (e[i].x==e[i+1].x) insert(e[i].d,e[i+1].d,2*(e[i+1].y-e[i].y));
40     sort(e+1,e+m+2+1,CMP);
41     for (int i=1;i<m+2;i++) if (e[i].y==e[i+1].y) insert(e[i].d+m+2,e[i+1].d+m+2,2*(e[i+1].x-e[i].x));
42     for (int i=1;i<=m;i++) insert(i,i+m+2,1);
43     insert(m+1,m+m+3,0),insert(m+2,(m+2)*2,0);
44     printf("%d",spfa());
45 }
原文地址:https://www.cnblogs.com/Comfortable/p/10310804.html