湖南省第十二届大学生计算机程序设计竞赛 F 地铁 多源多汇最短路

 

1808: 地铁


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

题解:

    现在假设i号线在深度i的世界里跑

   换线相当于换层

    然后换乘站相当于一个垂直通道,拆出一些点放到对应的层里

    然后按照深度从小到大连……

   你从1楼上到3楼就和你从1楼上到2楼,再从2楼上到3楼是一样的

   连边侯跑一发最短路就好了 ,spfa超时

   感谢quailty的题解和代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
typedef long long LL;
const LL INF = (1LL<<60)-1;
const double Pi = acos(-1.0);
const int N = 1e5+10, M = 1e6+11, mod = 1e9+7, inf = (1<<30)-1;

LL dist[N<<1];
int vis[N<<1];
struct Edge
{
    int a,b,t;
    Edge(int _a=0,int _b=0,int _t=0) : a(_a), b(_b), t(_t) {}
};
struct qnode {
        LL v,c;
        qnode(LL _v=0,LL _c=0) : v(_v), c(_c) {}
        bool operator < (const qnode &r) const
        {
            return c > r.c;
        }
};
vector< Edge > tmp[N<<1];
vector< pair<int,int > > G[N<<2];
vector<pair<int ,int > > p[N<<1];
void Add(int u,int v,int w) {
        G[u].push_back(make_pair(v,w));
        G[v].push_back(make_pair(u,w));
}
void init()  {
        for(int i = 0; i < N; ++i) p[i].clear(), tmp[i].clear();
        for(int i = 0; i < 4 * N; ++i) G[i].clear();
}
void Dij(int n,int u) {
        for(int i = 0; i <= n; ++i) dist[i] = INF, vis[i] = 0;
        priority_queue<qnode> q;
        for(int i = 0; i < p[u].size(); ++i) {
            dist[p[u][i].first] = 0;
            q.push(qnode{p[u][i].first,0});
        }
        while(!q.empty()) {
                int k = q.top().v;
                q.pop();
               if(vis[k]) continue;
               vis[k] = 1;
               for(int i = 0; i < G[k].size(); ++i)
               {
                   int v = G[k][i].first;
                   int c = G[k][i].second;
                   if(!vis[v] && dist[v] > dist[k] + c) {
                    dist[v] = dist[k] + c;
                    q.push(qnode{v,dist[v]});
                   }
               }
        }
}
int n,m;
int main() {
        while(scanf("%d%d",&n,&m)!=EOF) {
            init();
            for(int i = 1; i <= m; ++i) {
                int a,b,c,t;
                scanf("%d%d%d%d",&a,&b,&c,&t);
                tmp[c].push_back(Edge(a,b,t));
            }
            int tot = 0;
            for(int i = 0; i < N; ++i) {
                for(int j = 0; j < tmp[i].size(); ++j) {
                    int v[2] = {tmp[i][j].a,tmp[i][j].b}, w = tmp[i][j].t;
                    for(int _=0;_<2;++_){
                        int u = v[_];
                        if(p[u].empty() || p[u].back().second < i) {
                            p[u].push_back(make_pair(++tot,i));
                            int s = p[u].size();
                            if(s > 1) Add(p[u][s-2].first,p[u][s-1].first,p[u][s-1].second-p[u][s-2].second);
                        }
                    }
                    Add(p[v[0]].back().first,p[v[1]].back().first,w);
                }
            }
            Dij(tot,1);
            LL ans = INF;
            for(int i = 0; i < p[n].size(); ++i)  
                ans = min( ans, dist[p[n][i].first]);
            printf("%lld\n",ans);
        }
        return 0;
}

 

转载于:https://www.cnblogs.com/zxhl/p/5842755.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值