P4568 [JLOI2011] 飞行路线

written on 2022-05-26

第一次写分层图最短路的题,就以这道题作为一个模板题好了。

分层图最短路听起来是一个很新颖很高端的算法,但是其本质实际上很简单。

首先介绍其适用题目的特征:一般题目给出的信息会包括有几条免费路径,让你求出在有几条免费路径的前提下,到达终点的最短路径。

然后再来看看解决方法,这时分层图最短路就派上用场了。我们可以在原图的基础上,再建立 k 层的点,对于相邻不同层之间的点,连上边权为 0 的边,这样一来,我们将 选免费路径 视为跨层相邻的边,将 不选 视为同层的点。那么最终的答案就是所有层里面 End 的最小值。

要注意的点,就是数组的大小问题,因为 n 个点,扩展了 k 层,总共 k+1 层,因此 n 要开到原来的 k+1 倍大小,同理计算 m,应为4×(n+m)×(k+1)

细节处理详见代码

#include<bits/stdc++.h>
#define N 110005//n*(k+1)
#define M 2500005//4(n+m)k
using namespace std;
int n,m,k,s,t;
int tot,ver[M],edge[M],nxt[M],head[N];
void add_E(int x,int y,int z){ver[++tot]=y,edge[tot]=z,nxt[tot]=head[x],head[x]=tot;}
struct F
{
	int x,v;
	bool operator<(const F &p) const{return v>p.v;}
};
priority_queue<F> q;
int d[N];
bool mark[N];
void Dijkstra()
{
	memset(d,0x7f,sizeof(d));
	d[s]=0;
	q.push((F){s,0});
	while(q.size())
	{
		int x=q.top().x;
		q.pop();
		if(mark[x]) continue;
		mark[x]=1;
		for(int i=head[x];i;i=nxt[i])
		{
			int y=ver[i],z=edge[i];
			if(d[y]>d[x]+z)
			{
				d[y]=d[x]+z;
				q.push((F){y,d[y]});
			}
		}
	}
}
int main()
{
	scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
	s++,t++;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		x++,y++;
		for(int j=0;j<k;j++)
		{
			add_E(x+j*n,y+(j+1)*n,0),add_E(y+j*n,x+(j+1)*n,0);
			add_E(x+j*n,y+j*n,z),add_E(y+j*n,x+j*n,z);
		}
		add_E(x+k*n,y+k*n,z),add_E(y+k*n,x+k*n,z);
	}//41*50000=2050000
	for(int i=1;i<=n;i++)
		for(int j=0;j<k;j++) add_E(i+j*n,i+(j+1)*n,0);
	//10000*10=100000
	Dijkstra();
	int ans=2e9;
	for(int i=0;i<=k;i++) ans=min(ans,d[t+i*n]);
	printf("%d\n",ans);
}
posted @   Freshair_qprt  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示