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
Hint
对于10%的数据m=0
对于 30%的数据,n ≤ 50, m ≤ 1000;
对于 60%的数据,n ≤ 500, m ≤ 2000;
对于 100%的数据,n ≤ 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 }