地铁(最短路)

1808: 地铁

Time Limit: 5 Sec     Memory Limit: 128 Mb     Submitted: 1466     Solved: 350    


Description

Bobo 居住在大城市 ICPCCamp。

ICPCCamp 有 n 个地铁站,用 1,2,…,n 编号。 m 段双向的地铁线路连接 n 个地铁站,其中第 i 段地铁属于 ci 号线,位于站 ai,bi 之间,往返均需要花费 ti 分钟(即从 ai 到 bi 需要 ti 分钟,从 bi 到 ai 也需要 ti 分钟)。
众所周知,换乘线路很麻烦。如果乘坐第 i 段地铁来到地铁站 s,又乘坐第 j 段地铁离开地铁站 s,那么需要额外花费 |ci-cj | 分钟。注意,换乘只能在地铁站内进行。
Bobo 想知道从地铁站 1 到地铁站 n 所需要花费的最小时间。
 

Input

输入包含不超过 20 组数据。
每组数据的第一行包含两个整数 n,m (2≤n≤105,1≤m≤105).
接下来 m 行的第 i 行包含四个整数 ai,bi,ci,ti (1≤ai,bi,ci≤n,1≤ti≤109).
保证存在从地铁站 1 到 n 的地铁线路(不一定直达)。
 

Output

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

Sample Input

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

Sample Output

1

3

2

// 貌似是最短路模板题,但是,用点来跑最短路显然是错的,因为,每次松弛都不能记录是由哪条线路松弛的。为了知道是怎么松弛的。

我们可以用边来跑最短路,dis[i]  表示由 i 边到达 edge[i].to 点的最短路,这样可以愉快的松弛所有边了!有的大牛用了拆点的方法,就是把一个点分成多个线路的点,建图都比较难想,还是比较麻烦

  1 # include <cstdio>
  2 # include <cstring>
  3 # include <cstdlib>
  4 # include <iostream>
  5 # include <vector>
  6 # include <queue>
  7 # include <stack>
  8 # include <map>
  9 # include <bitset>
 10 # include <sstream>
 11 # include <set>
 12 # include <cmath>
 13 # include <algorithm>
 14 #pragma comment(linker,"/STACK:102400000,102400000")
 15 using namespace std;
 16 #define LL          long long
 17 #define lowbit(x)   ((x)&(-x))
 18 #define PI          acos(-1.0)
 19 #define INF         0x3f3f3f3f3f3f3f3f
 20 #define eps         1e-8
 21 #define MOD         1000000007
 22 
 23 inline int scan() {
 24     int x=0,f=1; char ch=getchar();
 25     while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
 26     while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
 27     return x*f;
 28 }
 29 inline void Out(int a) {
 30     if(a<0) {putchar('-'); a=-a;}
 31     if(a>=10) Out(a/10);
 32     putchar(a%10+'0');
 33 }
 34 #define MX 100005
 35 /**************************/
 36 struct Edge
 37 {
 38     int to,c;
 39     int dis;
 40     int nex;
 41 }edge[MX*2];
 42 struct Node
 43 {
 44     LL dis;
 45     int dex;
 46     bool operator < (const Node & x)const{return dis>x.dis;}
 47 };
 48 int n,m;
 49 int rm;
 50 int hlist[MX];
 51 LL dis[MX*2];
 52 bool vis[MX*2];
 53 void add_edge(int u,int v,int c,int d)
 54 {
 55     edge[rm] = (Edge){v,c,d,hlist[u]};
 56     hlist[u] = rm++;
 57     edge[rm] = (Edge){u,c,d,hlist[v]};
 58     hlist[v] = rm++;
 59 }
 60 
 61 void Dij(int s,int t)
 62 {
 63     memset(vis,0,sizeof(vis));
 64     memset(dis,0x3f,sizeof(dis));
 65     LL ans = INF;
 66     priority_queue<Node> Q;
 67     for (int i=hlist[1];i!=-1;i=edge[i].nex)
 68     {
 69         dis[i] = edge[i].dis;
 70         Q.push((Node){edge[i].dis,i});
 71     }
 72     while (!Q.empty())
 73     {
 74         Node now = Q.top(); Q.pop();
 75         int dx = now.dex;
 76         int u = edge[dx].to;
 77         if (vis[dx]) continue;
 78         vis[dx]=1;
 79         if (u==t) ans = min(ans,dis[dx]);
 80         for (int i=hlist[u];i!=-1;i=edge[i].nex)
 81         {
 82             if (!vis[i]&&dis[i]>dis[dx]+abs(edge[i].c-edge[dx].c)+edge[i].dis)
 83             {
 84                 dis[i] = dis[dx]+abs(edge[i].c-edge[dx].c)+edge[i].dis;
 85                 Q.push((Node){dis[i],i});
 86             }
 87         }
 88     }
 89     printf("%lld
",ans);
 90 }
 91 
 92 int main()
 93 {
 94     while (scanf("%d%d",&n,&m)!=EOF)
 95     {
 96         rm=0;
 97         memset(hlist,-1,sizeof(hlist));
 98         for (int i=1;i<=m;i++)
 99         {
100             int u,v,c,d;
101             u=scan(); v=scan();
102             c=scan(); d=scan();
103             add_edge(u,v,c,d);
104         }
105         Dij(1,n);
106     }
107     return 0;
108 }
View Code
原文地址:https://www.cnblogs.com/haoabcd2010/p/7356183.html