题意:
有n个点,m条地铁线,每条地铁线有一个三个值,分别表示这条地铁线上车的费用,坐一站的费用,和这条地铁线包含几个点,现在你需要从第 s 个地铁站到达第 t 个地铁站,问你至少需要花费多少钱?
做法:
和之前两个题目一样的做法,分层图最短路,不过这里的代码实现采用建虚点的方式,也就是说,对于每个点,我们将他在m个地铁线上的时候看作不一样的点,并且额外定义一个虚点表示下车,从m个地铁线上的点走到对应的虚点表示下车,不需要花钱,反之,表示上车,需要花费对应地铁线的上车费,建图完成之后直接跑最短路即可得到最小花费。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 6e5;
const ll mod = 1e9 + 7;
const ll inf = 1e18 + 7;
struct edge
{
int to;
ll w;
int nex;
}e[MAXN * 2];
int head[MAXN], tot;
ll dis[MAXN];
bool vis[MAXN];
void init()
{
memset(head, -1, sizeof(head));
tot = 1;
for (int i = 0; i < MAXN; i++)
dis[i] = inf;
}
void add(int a, int b, ll c)
{
e[tot] = edge{ b,c,head[a] };
head[a] = tot++;
}
#define Pair pair<int,int>
void dij(int s)
{
priority_queue<Pair, vector<Pair>, greater<Pair> >q;
q.push(Pair{ 0,s });
dis[s] = 0;
while (!q.empty())
{
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = true;
for (int i = head[u]; i + 1; i = e[i].nex)
{
int v = e[i].to;
if (dis[v] > dis[u] + e[i].w)
{
dis[v] = dis[u] + e[i].w;
q.push(Pair{ dis[v],v });
}
}
}
}
int n, m, s, t;
int in[1005];
int main()
{
init();
scanf("%d%d%d%d", &n, &m, &s, &t);
int a, b, cnt;
for (int i = 0; i < m; i++)
{
scanf("%d%d%d", &a, &b, &cnt);
for (int j = 0; j < cnt; j++)
{
scanf("%d", &in[j]);
if (j > 0)
{
add(i * n + in[j - 1], i * n + in[j], b);
add(i * n + in[j], i * n + in[j - 1], b);
}
add(i * n + in[j], m * n + in[j], 0);
add(m * n + in[j], i * n + in[j], a);
}
}
dij(m * n + s);
if (dis[m * n + t] == inf)
dis[m * n + t] = -1;
printf("%lld\n", dis[m * n + t]);
} 
京公网安备 11010502036488号