CSUOJ—1808

D - 地铁

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

[分析]
出的挺不错的一道最短路了.......用点做最短路的话考虑不到当前点经过换路过有可能成为新的最短路的情况,所以考虑用边当点做一次最短路...
考虑到这一点还不够...所以说这道题出的非常不错...因为把边当点时,遍历复杂度变高,所以单纯的dijkstra会超时的,所以需要用优先队列进行优化.....代码实现的问题了..
[代码]
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>  
#include <queue>
using namespace std;  
#define INF 0x3f3f3f3f3f3f3f3f  

struct xx{  
    int v,c,w,next;  
    xx(){};  
    xx(int q,int r,int e):v(q),c(r),w(e){}  
}a[501000];

struct qq{
	int id;
	long long diss; 
	qq(int q1,long long q2):id(q1),diss(q2){};  
	friend bool operator <(qq a,qq b)  
    {  
        return a.diss>b.diss;  
    }  
};

int n,m,len;  
long long dis[201000];
int vis[201000];  
int father[201000];  

void bfs()
{  
    memset(vis,0,sizeof(vis));  
    for(int i=0;i<=len;i++) dis[i]=INF;
	priority_queue<qq>q;  
    for(int i=father[1];i!=-1;i=a[i].next) dis[i]=a[i].w,q.push(qq(i,dis[i]));  
    long long ans=INF;
	while(!q.empty())  
    {  
        qq tt=q.top();
		q.pop();
        int now=tt.id;
        vis[now]=1;  
        int u=a[now].v;  
        if(u==n){ans=min(ans,dis[now]);continue;}
		for(int i=father[u];i!=-1;i=a[i].next)  
        {  
            int v=a[i].v;  
            if(!vis[i]&&dis[i]>dis[now]+a[i].w+abs(a[i].c-a[now].c))  
            {  
                dis[i]=dis[now]+a[i].w+abs(a[i].c-a[now].c);  
                q.push(qq(i,dis[i]));
			}  
        }  
    }  
    printf("%lld\n",ans);
}  

int main()  
{  
    while(scanf("%d%d",&n,&m)!=EOF)  
    {  
    	memset(father,-1,sizeof(father));  
    	len=0;  
        for(int i=0;i<m;i++)  
        {  
            int u,v,c,w;scanf("%d%d%d%d",&u,&v,&c,&w);  
            a[len].v=v;a[len].w=w;a[len].c=c;a[len].next=father[u];father[u]=len++;
            a[len].v=u;a[len].w=w;a[len].c=c;a[len].next=father[v];father[v]=len++;  
        }  
        bfs();
    }  
}  




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值