【JLOI2011】飞行路线
题目描述
Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在nn个城市设有业务,设这些城市分别标记为00到n-1n−1,一共有mm种航线,每种航线连接两个城市,并且航线有一定的价格。
Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多kk种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?
输入格式
数据的第一行有三个整数,n,m,kn,m,k,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,s,ts,t,分别表示他们出行的起点城市编号和终点城市编号。
接下来有m行,每行三个整数,a,b,ca,b,c,表示存在一种航线,能从城市aa到达城市bb,或从城市bb到达城市aa,价格为cc。
输出格式
只有一行,包含一个整数,为最少花费
输入 #1
5 6 1
0 4 0 1 5 1 2 5 2 3 5 3 4 5 2 3 3 0 2 100
输出 #1
8
【解题思路】
分层图模板题
我们将每个点拆成k个,这样子在路径上就能够表现出,选择简化这个点到另外一个点的路径对结果的影响
因为刚好是k层,所以能够优化的路径也就至多只有k层,保证了选择k条路径的前提
有点 u ,v ,令第 j - 1 层的 u 到第 j 层的 v 连边,代价为 0 ,这样子就能够表示这条路径被优化,同时又消耗了一次免费机会
注意:因为是双向边,所以同时也要连一条反向边
第 j 层的 u ,v 同时也要连一条边,代价为 c ,令优化过的 u 能够在不优化的情况下到达 v
得到这个新的图之后,我们在上面跑一遍最短路,就能够得到正确结果
因为最短路已经利用所有的 k 次机会优化了整个过程
【代码】
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<cstring> #define ll long long using namespace std; typedef pair<int, int> P; const int MAXN = 110010; const int MAXM = 4100010; const ll INF = (1ll << 62) - 1; struct note { int to; int nt; ll cost; }; struct edge { note arr[MAXM]; int st[MAXN]; ll dis[MAXN]; int top; int n, m, s, t,k; edge() { memset(st, -1, sizeof(st)); memset(dis, -1, sizeof(dis)); top = 0; } void read() { top = 0; scanf("%d%d%d", &n, &m, &k); scanf("%d%d", &s, &t); s++, t++; for (int i = 1; i <= m; i++) { int u, v; ll c; scanf("%d%d%lld", &u, &v, &c); u++, v++; add(u, v, c); add(v, u, c); for (int j = 1; j <= k; j++) { add(u+( j - 1 )*n, v + j*n, 0); add(v+( j - 1 )*n, u + j*n, 0); add(u + j * n, v + j * n, c); add(v + j * n, u + j * n, c); } } for (int i = 1; i <= k; ++i) { add(t + (i - 1)*n, t + i * n,0); } t += k * n; n = n * (k+1)+1; } void add(int x, int y, ll c) { top++; arr[top] = { y,st[x],c }; st[x] = top; } ll min_dis() { priority_queue<P,vector<P>,greater<P> > q; fill(dis+1, dis + n+1, INF); dis[s] = 0; q.push(P(0, s)); while (!q.empty()) { P p = q.top();q.pop(); int v = p.second; if (dis[v] < p.first) continue; for (int i = st[v]; i != -1; i = arr[i].nt) { int to = arr[i].to; if (dis[to] > dis[v] + arr[i].cost) { dis[to] = dis[v] + arr[i].cost; q.push(P(dis[to], to)); } } } return dis[t]; } }; edge road; int main() { road.read(); printf("%lld", road.min_dis()); return 0; }