P4568 [JLOI2011] 飞行路线
这道题目是一道单源最短路的问题,但是想要ac这道题目还需要使用分层图的知识,考虑到这道题目的数据范围,要使用堆优化的Dijkstra算法,求最短路的算法就不再过多赘述了,这里就主要探讨一下什么是分层图。
分层图
关于什么时候会用到分层图,我目前遇到的有两种情况,这题是其中一种,还有一种我会在下一篇题解里面讲解,这题对应的情况属于题目会给你k次权力,你可以用这k次权力改变图中的k条边的权值,这个时候可以建立k条边来对应k种选择,每向下一张图跳跃便代表使用了一次权力。
(自己做的图片,凑合着看吧)
每一层是一份图,题目给了你几次权力就建几层图,每一层图片都会有一个指向下一层图的目标位置的特殊权线,在运行Dijkstra的时候会自己运行。
for(int j = 1 ; j <= k ; j++)
{
add(j * n + a , j * n + b , c);
add(j * n + b , j * n + a , c);
add((j - 1) * n + a , j * n + b , 0);
add((j - 1) * n + b , j * n + a , 0);
}
以上便是建分层图的代码,建完分层图后直接运行Dijkstra然后遍历(k + 1)次来寻找最小值。
最后贴上AC代码
//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize("Os")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("Og")
//#pragma GCC optimize("inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <ll , ll> pii;
typedef priority_queue <ll ,vector<ll> ,greater<ll> > xiao;
typedef priority_queue <ll ,vector<ll> ,less<ll> > da;
const int N=3e6 + 10,M = 0x3f3f3f3f,NN = 1e6 + 10;
const ull P = 131;
int h[N],e[N],ne[N],idx,w[N];
int n,m,k,sta,en;
int dist[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx++;
}
void dijkstra()
{
memset(dist , M , sizeof dist);
dist[sta] = 0;
priority_queue <pii , vector<pii> , greater<pii> > heap;
heap.push({0 , sta});
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second,distance = t.first;
if(st[ver])
{
continue;
}
st[ver] = 1;
for(int i = h[ver] ; i != -1 ; i = ne[i])
{
int j = e[i];
if(dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j] , j});
}
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0),cout.tie(0);
memset(h , -1 , sizeof h);
cin>>n>>m>>k>>sta>>en;
for(int i = 1 ; i <= m ; i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a , b , c);
add(b , a , c);
for(int j = 1 ; j <= k ; j++)
{
add(j * n + a , j * n + b , c);
add(j * n + b , j * n + a , c);
add((j - 1) * n + a , j * n + b , 0);
add((j - 1) * n + b , j * n + a , 0);
}
}
dijkstra();
int minn = dist[en];
for(int i = 1 ; i <= k ; i++)
{
minn = min(minn , dist[i * n + en]);
}
cout<<minn;
}