分层图,建图,最短路
题意:
分析:
首先来看看我当时的思路吧!
我们很容易发现这是个最短路问题,但线路的存在很棘手。雨神说过,图论的难点在于建图!如果成功建图接下来就只是套板子了。那来看看我们如何建图。
我上来也没有思路,后是从实际生活入手的。
想象一下,我们在站点i我们可以坐1,2,3三路高铁,登上1号高铁掏钱a1,登上2号高铁掏钱a2,登上3号高铁掏钱a3
然后我们登上了高铁,假设我们登上了高铁1号线,我们向前开开了一站到达了j站的高铁上,这时我们要在花费b1然后我们从j站的高铁上下来,不用掏钱。
从i站到j站是不是就是这个过程。那我们就模仿这个过程建图就好了嘛。
除了站点之外,我们再建立一个高铁站不就好了,从站点跑上高铁站要是收费,从高铁站跑下站点不要收费。
高铁站线路移动的消耗为b
以样例为例:
5 2 1 4
2 2 3 1 3 5
2 1 4 2 3 4 5
第一条线路:(我们以6,7,8来表示高铁站)
第二条线路:(我们以9,10,11来表示高铁站)
那么合起来就是:
是不是,我们完美的模仿了高铁的功能,并且没有添加其他的功能。
如此我们便解决了这个问题!
在遍历每条线路时,对遍历的点给他建一个高铁站,这条线路遍历完后,对此线路的高铁站再建双向边。
最后再用dijstra算法就完事了。
代码如下:
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<functional>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
struct edge { int to, cost; };
const int max_n = 7e5;
const ll inf = 2e18;
vector<edge> G[max_n];
ll d[max_n];
int n, m;
void dijstra(int s) {
fill(d + 1, d + 1 + n, inf);
priority_queue<pll,vector<pll>,greater<pll>> que;
d[s] = 0;que.push({ d[s],s });
while (!que.empty()) {
pll p = que.top();que.pop();
if (p.first > d[p.second])continue;
d[p.second] = p.first;
for (int i = 0;i < G[p.second].size();i++) {
edge e = G[p.second][i];
if (d[e.to] > d[p.second] + e.cost) {
d[e.to] = d[p.second] + e.cost;
que.push({ d[e.to],e.to });
}
}
}
}
int main() {
ios::sync_with_stdio(0);
int s, t;
cin >> n >> m >> s >> t;
for (int i = 1;i <= m;i++) {
int a, b, c;cin >> a >> b >> c;
int st = n + 1;
for (int j = 1;j <= c;j++) {
int node;cin >> node;n++;
G[n].push_back({ node,0 });
G[node].push_back({ n,a });
}
for (int j = st;j < n;j++) {
G[j].push_back({ j + 1,b });
G[j + 1].push_back({ j,b });
}
}
dijstra(s);
if (d[t] == inf)cout << -1 << endl;
else cout << d[t] << endl;
}做完,来看题解后才发现这是一种被称为分层图的问题。不说了,去研究研究

京公网安备 11010502036488号