D - 地铁
Bobo 居住在大城市 ICPCCamp。
ICPCCamp 有 n 个地铁站,用 1,2,…,n 编号。 m 段双向的地铁线路连接 n 个地铁站,其中第 i 段地铁属于 c
i 号线,位于站 a
i,b
i 之间,往返均需要花费 t
i 分钟(即从 a
i 到 b
i需要 t
i 分钟,从 b
i 到 a
i 也需要 t
i 分钟)。
众所周知,换乘线路很麻烦。如果乘坐第 i 段地铁来到地铁站 s,又乘坐第 j 段地铁离开地铁站 s,那么需要额外花费 |c
i-c
j | 分钟。注意,换乘只能在地铁站内进行。
Bobo 想知道从地铁站 1 到地铁站 n 所需要花费的最小时间。
输入包含不超过 20 组数据。
每组数据的第一行包含两个整数 n,m (2≤n≤10
5,1≤m≤10
5).
接下来 m 行的第 i 行包含四个整数 a
i,b
i,c
i,t
i (1≤a
i,b
i,c
i≤n,1≤t
i≤10
9).
保证存在从地铁站 1 到 n 的地铁线路(不一定直达)。
3 3 1 2 1 1 2 3 2 1 1 3 1 1 3 3 1 2 1 1 2 3 2 1 1 3 1 10 3 2 1 2 1 1 2 3 1 1
1 3 2
[分析]
出的挺不错的一道最短路了.......用点做最短路的话考虑不到当前点经过换路过有可能成为新的最短路的情况,所以考虑用边当点做一次最短路...
考虑到这一点还不够...所以说这道题出的非常不错...因为把边当点时,遍历复杂度变高,所以单纯的dijkstra会超时的,所以需要用优先队列进行优化.....代码实现的问题了..
[代码]
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
struct xx{
int v,c,w,next;
xx(){};
xx(int q,int r,int e):v(q),c(r),w(e){}
}a[501000];
struct qq{
int id;
long long diss;
qq(int q1,long long q2):id(q1),diss(q2){};
friend bool operator <(qq a,qq b)
{
return a.diss>b.diss;
}
};
int n,m,len;
long long dis[201000];
int vis[201000];
int father[201000];
void bfs()
{
memset(vis,0,sizeof(vis));
for(int i=0;i<=len;i++) dis[i]=INF;
priority_queue<qq>q;
for(int i=father[1];i!=-1;i=a[i].next) dis[i]=a[i].w,q.push(qq(i,dis[i]));
long long ans=INF;
while(!q.empty())
{
qq tt=q.top();
q.pop();
int now=tt.id;
vis[now]=1;
int u=a[now].v;
if(u==n){ans=min(ans,dis[now]);continue;}
for(int i=father[u];i!=-1;i=a[i].next)
{
int v=a[i].v;
if(!vis[i]&&dis[i]>dis[now]+a[i].w+abs(a[i].c-a[now].c))
{
dis[i]=dis[now]+a[i].w+abs(a[i].c-a[now].c);
q.push(qq(i,dis[i]));
}
}
}
printf("%lld\n",ans);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(father,-1,sizeof(father));
len=0;
for(int i=0;i<m;i++)
{
int u,v,c,w;scanf("%d%d%d%d",&u,&v,&c,&w);
a[len].v=v;a[len].w=w;a[len].c=c;a[len].next=father[u];father[u]=len++;
a[len].v=u;a[len].w=w;a[len].c=c;a[len].next=father[v];father[v]=len++;
}
bfs();
}
}