题目
Description
moreD城的城市轨道交通建设终于全部竣工,由于前期规划周密,建成后的轨道交通网络由 2n 条地铁线路构成,组成了一个 n 纵 n 横的交通网。如下图所示,这 2n 条线路每条线路都包含 n 个车站,而每个车站都在一组纵横线路的交汇处。
出于建设成本的考虑,并非每个车站都能够进行站内换乘,能够进行站内换乘的地铁站共有 m 个,在下图中,标上方块标记的车站为换乘车站。已知地铁运行 1 站需要 2 分钟,而站内换乘需要步行 1 分钟。 你的最后一个作业就是算出,在不中途出站的前提下,从学校回家最快需要多少时间(等车时间忽略不计)。
Input
第一行有两个整数 n, m。接下去 m 行每行两个整数 x, y,表示第 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%的数据,n ≤ 50, m ≤ 1000;
对于 60%的数据,n ≤ 500, m ≤ 2000;
对于 100%的数据,n ≤ 20000, m ≤ 100000;
分析
-
此题的决策为转向,由于只存在横向和纵向两个放学,我们对这两个方向分别建立一层。即一层只连原图横向边,一层只连纵向边。
对于转向这个决策,将决策前的状态和决策后的状态间连接一条权值为决策代价的边,表示付出该代价转换了状态。
在本题中,即上下两层对应点连接一条权值为1的边,层内边权均为2.
然后跑最短路即可。
- 简单点讲,就是首先将同一横排与竖排上下所有点连边
- 然后交汇点其实就是一个转向的点
- 将交汇的点x与y连接跑最短路即可
代码
1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 #include<algorithm> 5 #define M 800001 6 #define N 200001 7 #define inf 0x3f 8 using namespace std; 9 struct sb 10 { 11 int x,y,bh; 12 }a[N]; 13 struct edge 14 { 15 int next,to,val; 16 }e[M]; 17 int n,m; 18 bool cmp(sb a,sb b) 19 { 20 if (a.x==b.x) return a.y<b.y; 21 return a.x<b.x; 22 } 23 bool CMP(sb a,sb b) 24 { 25 if (a.y==b.y) return a.x<b.x; 26 return a.y<b.y; 27 } 28 int h[M],cs=1; 29 void add(int from,int to,int val) 30 { 31 e[cs].to=to; 32 e[cs].next=h[from]; //将它指向对应的下一层 33 e[cs].val=val; 34 h[from]=cs++; 35 } 36 void ins(int from,int to,int val) 37 { 38 add(from,to,val); 39 add(to,from,val); 40 } 41 queue <int> q; 42 int dis[M]; 43 bool v[M]; 44 void spfa() 45 { 46 memset(dis,0x3f,sizeof(dis)); 47 dis[m+1]=0; 48 v[m+1]=1; 49 q.push(m+1); 50 while (!q.empty()) 51 { 52 int x=q.front(); q.pop(); v[x]=0; 53 for (int i=h[x];i;i=e[i].next) 54 { 55 int to=e[i].to,val=e[i].val; 56 if (dis[to]>dis[x]+val) 57 { 58 dis[to]=dis[x]+val; 59 if (!v[to]) 60 { 61 v[to]=1; 62 q.push(to); 63 } 64 } 65 } 66 } 67 } 68 int main () 69 { 70 cin>>n>>m; 71 for (int i=1;i<=m+2;i++) 72 { 73 cin>>a[i].x>>a[i].y; 74 a[i].bh=i; 75 } 76 sort(a+1,a+m+3,cmp); 77 for (int i=1;i<=m+2;i++) 78 if (a[i].x==a[i+1].x) ins(a[i].bh,a[i+1].bh,2*(a[i+1].y-a[i].y)); //将同一行的的x连边,权值为2*(y1-y2) 79 sort(a+1,a+m+3,CMP); 80 for (int i=1;i<=m+2;i++) 81 if (a[i].y==a[i+1].y) ins(a[i].bh+m+2,a[i+1].bh+m+2,2*(a[i+1].x-a[i].x)); //同一列同上 82 for (int i=1;i<=m;i++) 83 ins(i,i+m+2,1); //将转车点x与y连边,权值为1 84 ins(m+1,2*m+3,0); ins(m+2,2*m+4,0); //终点,起点为0 85 spfa(); 86 if (1061109567==dis[m+2]) 87 cout<<-1; 88 else 89 cout<<dis[m+2]; 90 }