单源最短路径 Dijkstra (堆优化)

P4779 【模板】单源最短路径(标准版)

首先Dijkstra适用于单源最短路径,且没有没有负权边的图
1、当为稠密图时使用邻接矩阵存图,这时的复杂度为O(n^2) ;
2、当为稀疏图时使用邻接表存图,且这时配合优先队列(堆)后复杂度为O(n*log n) ;

<注意事项>
1、堆优化时pair<int,int>,是默认优先以第一个int来排序的,所以记得要把 dis 作为第一个参数。
2、当queue里元素是 pair<> 时,入队的时候要make_pair(),不要{ }。不要再用万能头了。(玄学T~ ~ ~ 吐槽洛谷编译器

Code1 O(nlogn):

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>

using namespace std;
const int N = 5e5+7;
const int INF = 0x3f3f3f3f; 
typedef pair<int,int> PII;

int h[N],e[N],ne[N],w[N],idx;	//有向图 
int n,m,s;
int dis[N];
bool st[N];

priority_queue<PII, vector<PII> , greater<PII> > heap;	 //当STL冗余较大时 最好开在外面;

void add(int a,int b,int v){
	e[idx] = b,w[idx] = v,ne[idx] = h[a],h[a] = idx++;
}

void dijkstra()
{
	for(int i=1;i<=n;i++) dis[i] = INF;
	dis[s] = 0;
	heap.push(make_pair(0,s));				// 这里一定要make_pair(), 不要{} ;
	while(heap.size()){
		auto a  = heap.top();
		heap.pop();
		int t = a.second ;
		if(st[t]) continue;
		st[t] = 1;
		for(int i = h[t] ; i!=-1 ;i = ne[i]){
			int j = e[i] , v = w[i];
			if(dis[j] > dis[t] + v){
				dis[j] = dis[t] + v;
				heap.push(make_pair(dis[j] , j));
			}
		}
	}
}

int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d%d%d",&n,&m,&s);
	memset(h,-1,sizeof h);
	int x,y,v;
	while(m--){
		scanf("%d%d%d",&x,&y,&v);
		add(x,y,v);
	}
	dijkstra();
	for(int i=1;i<=n;i++) {
		if(dis[i] != INF)printf("%d",dis[i]);
		if(i!=n) printf(" ");
	}
	printf("\n");
	return 0; 
 } 

Code2 O(n^2):

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 1e5+7;

int h[N],e[N*2],ne[N*2],w[N*2],idx;
int n,m,s;
int dis[N];
bool st[N];

void add(int a,int b,int v){
	e[idx] = b,w[idx] = v,ne[idx] = h[a],h[a] = idx++;
}

int dijkstra()
{
	memset(dis,0x3f,sizeof dis);
	dis[s] = 0;
	for(int i=0;i<n-1;i++){
		int t = -1;
		for(int j=1;j<=n;j++){
			if(!st[j] && (t==-1||dis[t]>dis[j]))
			t = j;
		}
		for(int i=h[t] ;i!=-1;i = ne[i]){
			int j = e[i];
			int v = w[i];
			if(!st[j])  dis[j] = min(dis[j],dis[t] + v);
		}
		st[t] = 1;
	}
}
int main()
{
	s = 1;
	cin>>n>>m;
	memset(h,-1,sizeof h);
	int x,y,v;
	while(m--){
		scanf("%d%d%d",&x,&y,&v); 
		add(x,y,v);
	}
	dijkstra();
	if(dis[n]!=0x3f3f3f3f) cout<<dis[n]<<"\n";
	else cout<<"-1\n";
	return 0; 
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值