2016湖南省省赛F-地铁(CSU1808)

1808: 地铁

Submit      Status      Time Limit:  5 Sec   | Memory Limit:  128 Mb   | Submitted:  870   | Solved:  202

Description

 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 所需要花费的最小时间。

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 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

Hint

Source

湖南省第十二届大学生计算机程序设计竞赛


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <climits>
#include <functional>

using namespace std;

#define LL long long
const LL INF=0x3f3f3f3f3f3f3f3f;

int n,m;
int s[100009],e[200009],nt[200009];
LL c[200009],t[200009];
LL dis[200009];

struct node
{
    int id;
    LL sum;
    friend bool operator <(node x,node y)
    {
        return x.sum>y.sum;
    }
}pre,nt1;

void Dijkstra(int ss)
{
    for(int i=1;i<=2*m;i++) dis[i]=INF;
    priority_queue<node>q;
    for(int i=s[ss];~i;i=nt[i])
    {
        pre.id=i;
        pre.sum=t[i];
        dis[i]=t[i];
        q.push(pre);
    }
    LL ans=INF;
    while(!q.empty())
    {
        pre=q.top();
        q.pop();
        int id=pre.id;
        int ee=e[id];
        if(ee==n) ans=min(ans,dis[id]);
        for(int i=s[ee];~i;i=nt[i])
        {
            if(dis[i]>dis[id]+t[i]+abs(c[i]-c[id]))
            {
                dis[i]=dis[id]+t[i]+abs(c[i]-c[id]);
                nt1.id=i;
                nt1.sum=dis[i];
                q.push(nt1);
            }
        }
    }
    printf("%lld\n",ans);
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        int cnt=1;
        memset(s,-1,sizeof s);
        memset(nt,-1,sizeof nt);
        int ss,ee;
        LL tt,cc;
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d %lld %lld",&ss,&ee,&cc,&tt);
            nt[cnt]=s[ss],s[ss]=cnt,e[cnt]=ee,c[cnt]=cc,t[cnt++]=tt;
            nt[cnt]=s[ee],s[ee]=cnt,e[cnt]=ss,c[cnt]=cc,t[cnt++]=tt;
        }
        Dijkstra(1);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值