C++ P4568 [JLOI2011]飞行路线 ---- Dijkstra+分层图

题目地址:https://www.luogu.org/problemnew/show/P4568

Dijkstra:https://blog.csdn.net/u012972031/article/details/83476580


分层图是什么

顾名思义,所谓的"分层图",就是分层的图。

分层图的用处

在某些情况下,需要在普通的图上算法的基础上增加一些特殊功能,如:某些边权值为0,且这些边是由我们动态生成的。这时候裸的Dijkstra显然无法胜任,那么我们就可以考虑一下使用分层图了。

分层图的实现方法

  • 第一种:同时建多个图,并将这些图连起来,就像链表一样。
  • 第二种:使用一个二维的dis[]数组,第二个下标储存层数。(这种方法比较快)

分层图的具体实现:

  • 第一种:
  • 第二种:
  • 使用DP方式(用于优化性能),在此不再出示图片

 

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int s,k,cnt=0,dis[1000010*20],head[1000010*20];
struct Edge{
	int v,w,next;
}e[500005*30];
struct Node{
	int u,d;
	bool const operator <(const Node& a)const{
		return d>a.d;
	}
};
void addEdge(int u,int v,int w){
	e[++cnt].v=v;
	e[cnt].w=w;
	e[cnt].next=head[u];
	head[u]=cnt;
}
void dijkstra(){
	dis[s]=0;
	priority_queue<Node> q;
	q.push((Node){s,0});
	while(!q.empty()){
		Node n=q.top();q.pop();
		int u=n.u,d=n.d;
		if(d!=dis[u])continue;
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].v,w=e[i].w;
			if(dis[u]+w<dis[v]){
				dis[v]=dis[u]+w;
				q.push((Node){v,dis[v]});
			}
		}
	}
}
int main(){
	int n,m;
	scanf("%d%d%d",&n,&m,&k);
	int t;
	scanf("%d%d",&s,&t);
	for(int i=1;i<=m;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		for(int i=0;i<=k;i++){
			int ta=i*n+a,tb=i*n+b;//tb往前连,ta往后连 
			addEdge(ta,tb,c); 
			addEdge(tb,ta,c);
			if(i!=k){//如果不是最后一个图 
				addEdge(tb,ta+n,0);//tb往前连 
				addEdge(ta,tb+n,0);//ta往后连  
			}
		}//普通建图
		/*
		连接节点:遍历所有加的点: 
			if(是最前面的图&&是最前面的点){
				连后面一个图自己后面的和自己 
			}else if(是最后面的图){
				不连 
			}else{
				连后面一个图自己前面的和自己
				连后面一个图自己后面的和自己
		}*/
		
	}
	for(int i=0;i<=n*30;i++)dis[i]=2000000000;
	dijkstra();
	printf("%d\n",dis[n*k+t]);
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值