P4568 [JLOI2011] 飞行路线

105 阅读2分钟

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;
}