链接:https://ac.nowcoder.com/acm/contest/949/J
来源:牛客网
题目描述
小雨所在的城市一共有 m 条地铁线,分别标号为 1 号线,2 号线,……,m 号线。整个城市一共有 n 个车站,编号为 1∼n。其中坐 i 号线需要花费 ai 的价格,每坐一站就需要多花费 bi 的价格。i 号线有 ci 个车站,而且这 ci 个车站都已知,如果某一站有多条地铁线经过,则可以在这一站换乘到另一条地铁线,并且能多次换乘。现在小雨想从第 s 个车站坐地铁到第 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 。
备注:
1 ≤ n ≤ 103, 1 ≤ m ≤ 500, 1 ≤ s,t ≤ n,1 ≤ ai,bi≤100 , 1 ≤ ci ≤ n, ∑ ci≤105
分析:
不同的地铁线路属于不同的层次,所以是分层图,但是不同层的图之间有相交,如果两两暴力连图时间复杂度会达到O(n*m2)
这里就要用到虚点,就是在原有分层图的基础上再加一层分层图,里面是1~n 所有点的虚点,用于作为中转站(相当于人在地铁站,但是还没决定做哪一号线路),所有点到其虚点的花费为0,而从虚点到对应点的花费为该点所在地铁线路的初始花费。
这样建图的时间复杂度就只有O(n*2m)了,同时在使用最短路算法时,起点s和终点t都选定在其虚点上(不然会有多个s和t,而且需要考虑从某一条地铁线路开始的花费)
对于点的编号,因为一条线路(一层分层图)上至多有n个点,所以不同线路的编号可以依次加上0、n、2n、… 、(m-1)* n,而虚点则加上 m* n。
以下代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<algorithm>
#define PII pair<int,int>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const int maxn=1e3+50;
const int maxm=500+