【CSU1808】地铁

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

对于每组数据,输出一个整数表示要求的值。
 
 
题解:分层图最短路。
每个地铁站按地铁线拆成若干站,这若干站之间按线号从小到大连,表示换乘地铁线。
 
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define gg puts("gg");
 4 #define ll long long
 5 #define mp make_pair
 6 #define pii pair<int, int>
 7 #define pli pair<ll, int>
 8 #define fi first
 9 #define se second
10 const int N = 1e5+50;
11 const ll inf = 1e16;
12 int n, m, tot;
13 struct edge{
14     int to, w;
15     edge(int to, int w):to(to), w(w){}
16     edge(){}
17 };
18 struct Edge{
19     int f, to, w;
20     Edge(int f, int to, int w): f(f), to(to), w(w){}
21     Edge(){}
22 };
23 vector<Edge> s[N];
24 vector< pii > newv[N];
25 vector<edge> ve[N*4];////
26 ll d[N*2];
27 void dijsktra(int n, int s){
28     for(int i = 1; i <= n; i++) d[i] = inf;
29     priority_queue< pli, vector<pli>, greater< pli > > Q;
30     for(int i = 0; i < newv[s].size(); i++){
31         int u = newv[s][i].se;
32         d[u] = 0;
33         Q.push( mp(0, u) );
34     }
35     while(!Q.empty()){
36         pli f = Q.top();
37         Q.pop();
38         ll dis = f.fi;
39         int x = f.se;
40         if(d[x] < dis)
41             continue ;
42         for(int i = 0; i < ve[x].size(); i++){
43             int to = ve[x][i].to, w = ve[x][i].w;
44             if(d[to] > dis+w){
45                 d[to] = dis+w;
46                 Q.push( mp(d[to], to) );
47             }
48         }
49     }
50 }
51 
52 int main(){
53     int u, v;
54     while(~scanf("%d%d", &n, &m)){
55         int a, b, c, t;
56         for(int i = 0; i < m; i++){
57             scanf("%d%d%d%d", &a, &b, &c, &t);
58             s[c].push_back( Edge(a, b, t) );
59         }
60 
61         tot = 0;
62         for(int i = 1; i <= n; i++){
63             for(int j = 0; j < s[i].size(); j++){
64                 int u = s[i][j].f, v = s[i][j].to, w = s[i][j].w;
65                 if(newv[u].empty()||newv[u].back().first < i) newv[u].push_back( mp(i, ++tot) );
66                 if(newv[v].empty()||newv[v].back().first < i) newv[v].push_back( mp(i, ++tot) );
67                 int uu = newv[u].back().se, vv = newv[v].back().se;
68                 ve[uu].push_back( edge(vv, w) );
69                 ve[vv].push_back( edge(uu, w) );
70             }
71         }
72         for(int i = 1; i <= n; i++){
73             for(int j = 1; j < newv[i].size(); j++){
74                 int u = newv[i][j-1].se, v = newv[i][j].se, w = newv[i][j].fi-newv[i][j-1].fi;
75                 ve[u].push_back( edge(v, w) );
76                 ve[v].push_back( edge(u, w) );
77             }
78         }
79 
80         dijsktra(tot, 1);
81         ll ans = inf;
82         for(int i = 0; i < newv[n].size(); i++){
83             int x = newv[n][i].se;
84             ans = min(ans, d[x]);
85         }
86         printf("%lld\n", ans);
87 
88         for(int i = 1; i <= n; i++){
89             s[i].clear();
90             newv[i].clear();
91         }
92         for(int i = 1; i <= tot; i++)
93             ve[i].clear();
94     }
95     return 0;
96 }

 

posted @ 2016-11-08 01:10  我在地狱  阅读(506)  评论(0编辑  收藏  举报