题目描述
小雨所在的城市一共有 m 条地铁线,分别标号为 1 号线,2 号线,……,m 号线。整个城市一共有 n 个车
站,编号为 1 ∼ n 1 \sim n 1∼n 。其中坐 i 号线需要花费 a i a_i ai 的价格,每坐一站就需要多花费 b i b_i bi 的价格。i 号
线有 c i c_i ci 个车站,而且这 c i c_i ci 个车站都已知,如果某一站有多条地铁线经过,则可以在这一站换乘到另
一条地铁线,并且能多次换乘。现在小雨想从第 s 个车站坐地铁到第 t 个车站,地铁等待时间忽略不计,
求最少花费的价格,若不能到达输出 -1 。(地铁是双向的,所以 s 可能大于 t)
输入描述:
第一行输入四个正整数 n,m,s,t,分别表示车站个数,地铁线数,起点站和终点站。
第二行到第 m + 1m+1 行,每行前三个数为 a i , b i , c i a_i,b_i,c_i ai,bi,ci ,分别表示坐 i 号线的价格,i 号线每坐一站多花
的价格,i 号线车站个数。接下来 c i c_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 : 1 \rightarrow 3: 1→3:花费 2;
换乘 2 号线:花费 2;
3 → 4 3 \rightarrow 4 3→4:花费 1;
所以最小总花费为 7 。
备注:
1
≤
n
≤
1
0
3
,
1
≤
m
≤
500
,
1
≤
s
,
t
≤
10
1 \leq n \leq 10^3, 1 \leq m \leq 500,1 \leq s,t \leq10
1≤n≤103,1≤m≤500,1≤s,t≤10
分层图最短路,每层都是n个节点,暴力建边是
O
(
n
m
2
)
O(nm^2)
O(nm2), 考虑现实情况,每个站都有一个大厅,所以不妨多一层图当做大厅,起点在s的大厅里,终点在t的大厅里,每层图的站点x都能直接连接x的大厅,花费为0,反之,则需要进入该条地铁线的
a
i
a_i
ai.
代码:
#include<bits/stdc++.h>
using namespace std;
#define Init(arr,val) memset(arr,val,sizeof(arr))
const int inf=0x3f3f3f3f,mod=9999991,MAXN=1000*505,MAXE=2e6+3e3;
typedef long long ll;
struct Edge{
int y,val,nxt;
}e[MAXE];
int cnt,head[MAXE];
inline void add(int x,int y,int val){
e[++cnt].y=y;
e[cnt].val=val;
e[cnt].nxt=head[x];
head[x]=cnt;
}
int n,m,s,t;
int dis[MAXE];
bool vis[MAXE];
struct Node{
int y,val;
bool operator<(const Node&other)const{return val>other.val;}
};
priority_queue<Node>heap;
void dijkstra(){
Init(dis,inf);
heap.push({n*n+s,0});
dis[n*n+s]=0;
while(!heap.empty()){
Node tmp=heap.top();
heap.pop();
int now=tmp.y;
if(vis[now])continue;
vis[now]=1;
for(int i=head[now];i;i=e[i].nxt){
int to=e[i].y;
int va=e[i].val;
if(!vis[to]&&dis[to]>dis[now]+va){
dis[to]=dis[now]+va;
heap.push({to,dis[to]});
}
}
}
}
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
cin>>n>>m>>s>>t;
for(int i=0;i<m;++i){
int a,b,c,x,y;
cin>>a>>b>>c>>x;
add(i*n+x,n*n+x,0);//i*n+x 即为第i层图编号为x的站点,他能去n*n+x的大厅,花费=0
add(n*n+x,i*n+x,a);//
while(--c){//--c,循环c-1次
cin>>y;
add(i*n+x,i*n+y,b);
add(i*n+y,i*n+x,b);
add(i*n+y,n*n+y,0);
add(n*n+y,i*n+y,a);
x=y;
}
}
dijkstra();
printf("%d",dis[n*n+t]==inf?-1:dis[n*n+t]);
return 0;
}