小雨坐地铁

链接:

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format:%lld

题目描述

小雨所在的城市一共有 m 条地铁线,分别标号为 1 号线,2 号线,……,m 号线。整个城市一共有 n 个车站,编号为 1∼n 。其中坐 i 号线需要花费 ai的价格,每坐一站就需要多花费 bi的价格。i 号线有 ci个车站,而且这 ci个车站都已知,如果某一站有多条地铁线经过,则可以在这一站换乘到另一条地铁线,并且能多次换乘。现在小雨想从第 ss 个车站坐地铁到第 t
个车站,地铁等待时间忽略不计,求最少花费的价格,若不能到达输出 -1 。(地铁是双向的,所以 s 可能大于 t)

输入描述:

第一行输入四个正整数 n,m,s,t分别表示车站个数,地铁线数,起点站和终点站。 第二行到第 m + 1行,每行前三个数为
ai,bi,ci,分别表示坐 i 号线的价格,i 号线每坐一站多花的价格,i 号线车站个数。接下来 ci个数,表示 i
号线的每一个车站的编号,单调递增。

输出描述:
共一行,一个数表示最小花费,若不能到达输出 -1 。
示例1
输入

5 2 1 4
2 2 3 1 3 5
2 1 4 2 3 4 5

输出

7

说明
坐 1 号线:花费 2;
1→3:花费 2;

换乘 2 号线:花费 2;
3→4:花费 1;

所以最小总花费为 7 。

题解:
我也是毫无头绪,不知道该怎么下手做,看完别人的题解,来讲讲自己的理解
我们要用到分层图
建立m+1层图,前m层自然就是每一条的地铁线,但地铁线是有可能交叉的,也就是拥有共同车站,所以在第m+1层给每个车站建立一个虚点,用于和前m层对应的车站相连,注意是建双向边,因为地铁可来回,从虚点到地铁线上需要花费,花费坐这条线的价格,从地铁线上到虚点花费为0
具体可以看看图:

例题中求1—>4 ,
从虚点1出发,到第一条线1,花费为2,
从1再到3 花费为2
从第一条线3再到虚点3 花费为0
虚点3到第二条线3 花费为2
从第二条线3到4 花费为1
总花费为7

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e8+2;
int n,m,s,t,head[maxn],dis[maxn],ant,x;;
priority_queue<pair<int,int> ,vector<pair<int,int> >,greater<pair<int,int> > >q;
struct Node{
   
int to,next,w;
}edge[maxn<<1];

void add(int u,int v,int w)
{
   
	edge[ant].next = head[u];
    edge[++ant].to = v;
	edge[ant].w = w;
	
	head[u] = ant;
}
void dijkstra(int s)
{
   
	int u,d,v;
    dis[s] = 0;
  
    q.push(pair<int,int> (0,s));
    while(!q.empty())
    {
   
        u = q.top().second;
		d = q.top().first;
        q.pop();
        if(d > dis[u]) continue;
        for(int i=head[u];i;i=edge[i].next)
        {
   
             v = edge[i].to;
            if(dis[v] > dis[u]+edge[i].w)
            {
   
                dis[v] = dis[u]+edge[i].w;
                q.push(pair<int,int> (dis[v],v));
            }
        }
    }
}
int main()
{
    
	int a,b,c;
    cin>>n>>m>>s>>t;

	for(int i=1;i<=n*(m+1);++i) dis[i] = maxn;
    
	for(int i=1;i<=m;++i)
    {
   
       
        cin>>a>>b>>c;
        int pre = -1;
        while(c--)
        {
   
            cin>>x;
            if(pre != -1)
            {
   
                add(i*n+x,i*n+pre,b);
                add(i*n+pre,i*n+x,b);
            }
            
            add(x,i*n+x,a);//虚边到火车站费用是做这个火车的费用 
            
			add(i*n+x,x,0);//火车站到虚边费用为0 
			
			pre = x;//存上一个车站 
        }
    }

    dijkstra(s);
    if(dis[t] == maxn) cout<<"-1";
    else cout<<dis[t];
    return 0;
}
全部评论

相关推荐

压力很大,面试官全程高压,问的问题不难,但是没有任何反馈,很慌张,也无算法。实习问了20分钟,一直问我你们做的有什么用,总时长一小时1.学校都有什么课程2.spring的ioc原理以及优点3.除了解耦还知道什么?4.springboot与spring区别,二者的源码看过没?Tomcat了解嘛?有没有具体看过5.spring的bean,面试官一直在重复一个思想问我懂不懂,完全没听过6.mybatis是干什么的?ibatis用过没?平常怎么写SQL?完全不写嘛?7.设计一个分布式双十一秒杀系统(前端,网关,缓存,数据库防超卖全设计)8.怎么做限流9.缓存与数据库一致性,你做异步要用户等你嘛?10.负载均衡怎么做11.多数据中心还是单数据中心,如果出现没卖完怎么做(到这完全不会了,面试官直接说换个话题吧)12.平常读书吗?13.上过哲学课嘛?14.兴趣爱好有没有15.对ai的看法16.来深圳有问题嘛?17.为什么不考研18.上大学带给了你什么?你提升在哪里,有没有具体的例子?反问:1.现在手机都有应用市场,应用宝怎么盈利?除了手机应用市场还是有人用,现在在做跨端,微软都有合作,之后会进军mac,主要做游戏,腾讯本身就是游戏大户。2.面试表现?整体评价一下会给到反馈。面完直接变HR面,今天HR面后,已经转为录用评估了,来牛客许个愿,暑期现在还没什么面试,希望能拿个offer之后再考虑要不要留在手子吧。
nunuking:三面压力这么大吗,面试的会议约了多长时间呀
面试问题记录
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务