CSU 1808 地铁(最短路)

来源:互联网 发布:linux mint vim配置 编辑:程序博客网 时间:2024/04/29 17:45

题意:n个地铁站,m条线路,地铁站之间花费t时间,不属于同一条线路的地铁站需要“转站”,即加上一个额外花费w(w为线路代号的差值)。 求1到n的最短时间

思路:由于有转站的影响,可以考虑将地铁站拆点,权值是他们的差值,或者直接以边作为点也是可以的


#include<bits/stdc++.h>using namespace std;const int maxn = 2e5+7;#define inf 1LL<<60#define LL long longint n,m,vis[maxn],head[maxn],tot=0;struct Node{int v,c,w,nxt;Node(){};Node(int vv,int cc,int ww):v(vv),c(cc),w(ww){}}edge[maxn<<1];void add_edge(int u,int v,int c,int w){edge[tot].v=v;edge[tot].w=w;edge[tot].c=c;edge[tot].nxt=head[u];head[u]=tot++;}void init(){memset(head,-1,sizeof(head));tot = 0;}LL d[maxn];LL dijkstra(){priority_queue<pair<LL,int> >q;LL ans = inf;memset(vis,0,sizeof(vis));for(int i = 0;i<=tot;i++)d[i]=inf;for(int i = head[1];~i;i=edge[i].nxt){d[i]=edge[i].w;q.push(make_pair(-d[i],i));}    while(!q.empty()){pair<LL,int>tmp = q.top();q.pop();int now = tmp.second;vis[now]=1;int u = edge[now].v;if(u==n)ans = min(ans,d[now]);for(int i = head[u];~i;i = edge[i].nxt){int v = edge[i].v;if(!vis[i] && d[i]>d[now]+edge[i].w+abs(edge[i].c-edge[now].c)){d[i]=d[now]+edge[i].w+abs(edge[i].c-edge[now].c);q.push(make_pair(-d[i],i));}}}return ans;}int main(){    while(scanf("%d%d",&n,&m)!=EOF){        init();for(int i = 1;i<=m;i++)        {int u,v,c,w;scanf("%d%d%d%d",&u,&v,&c,&w);add_edge(u,v,c,w);add_edge(v,u,c,w);}        printf("%lld\n",dijkstra());}}

Description

 Bobo 居住在大城市 ICPCCamp。

ICPCCamp 有 n 个地铁站,用 1,2,…,n 编号。 m 段双向的地铁线路连接 n 个地铁站,其中第 i 段地铁属于 c i 号线,位于站 a i,bi 之间,往返均需要花费 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 所需要花费的最小时间。

Input

输入包含不超过 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 的地铁线路(不一定直达)。

Output

对于每组数据,输出一个整数表示要求的值。

Sample Input

3 31 2 1 12 3 2 11 3 1 13 31 2 1 12 3 2 11 3 1 103 21 2 1 12 3 1 1

Sample Output

132


0 0
原创粉丝点击