单源最短路径

        实现弗洛伊德算法和迪杰斯特拉算法求单源最短路径

一、迪杰斯特拉算法:

默认源点为1,d【x】:源点到x的距离;

(x,y,z)表示x->y的边权为z,即dist[x][y]=z;

1.初始化源点到源点的距离d[1]为0,到其余各点的距离为正无穷。

2.找出一个未被标记的、d[x]最小的节点x,然后标记该节点x。

3.扫描节点x的所有出边(x,y,z),若d[y]>d[x]+z,则使用d[x]+z更新d[y]。

4.重复上述2、3操作,直到所有节点都被标记。

注意:该算法只使用于边权为非负数的情况。最终得到源点到各个点的最短路径。

代码:

#include<bits/stdc++.h>
using namespace std;

//dijkstra
const int N=10010;
int head[N],next[N],ver[N],edge[N],d[N];//ver终点,edge边权 ,d起点到该点的距离 
bool v[N];
int tot,n,m;

//利用大根堆维护当前最小距离,并用最小距离更新其他节点 
priority_queue< pair<int,int> >q;
//(x,y),权值为z 
void add(int x,int y,int z){
	ver[++tot]=y;
	edge[tot]=z;
	next[tot]=head[x];//此时head保存的是上一次的tot 
	head[x]=tot; 
}

void dijkstra(){
	memset(d,0x3f,sizeof(d));
	memset(v,0,sizeof(v));
	//初始化d[1]=0;
	d[1]=0;
	q.push(make_pair(0,1)); //d,y
	while(q.size()){
		int x=q.top().second;
		q.pop();
		if(v[x])continue;
		for(int i=head[x];i;i=next[i]){
			int y=ver[i],dxy=edge[i];//
			if(d[y]>d[x]+dxy){
				d[y]=d[x]+dxy;
				q.push(make_pair(-d[y],y));//大根堆转换成小根堆,-d[y]
			}
		}
	} 
	
}

int main(){
	cin>>n>>m;//n个点,m个边 
	//有向图 
	for(int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);//构建邻接表
	}
	dijkstra();
	for(int i=1;i<=n;i++){
		printf("%d\n",d[i]);
	} 
	return 0;
}

 

二、弗洛伊德算法:

邻接矩阵tim[x][y]表示的是x->y的边权。n个点,m条边

1.遍历n个顶点,作为中转点k。

2.对于每个中转点,当i!=j时,更新d[i][j]=min(d[i][j],d[i][k]+d[k][j])

代码:

#include<bits/stdc++.h>
using namespace std;

int n,m;
int tim[N][N];//Floyd的临界数组 


void Floyd(){
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i!=j){
					tim[i][j]=min(tim[i][j],tim[i][k]+tim[k][j]);
				}
			}
		}
	}
} 
int main(){
	cin>>n>>m;//n个点,m个边 
	//有向图 
	memset(tim,0x3f,sizeof(tim));
	for(int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		tim[x][y]=z;//构建临界数组 
	}

	Floyd();

	for(int i=1;i<=n;i++){
		printf("%d\n",tim[1][i]);
	} 
	return 0;
}

如果觉得不错,请点个赞吧,让我知道你的赞赏!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值