路径最短问题算法总结和实现(Floyd,Dijkstra,SPFA)

题目描述:求两个点之间的最短路径

输入:两个整数n,m(1<=n,m<=100)n的含义是节点的个数,m的含义是边的个数,接下来的m行输入三个整数i j c,分别表示开始结束节点和之间的费用

输出:从1到n节点之间的路径长度

Floyd算法:使用二维数组ans[i][j]保存从i到j的最短路径,不断在i和j之间插入节点k,检验k的到来是否路径减少,路径减少则更新ans[i][j]数组。适用于求多个节点之间的最短路径。

#include "stdio.h"
#include "limits.h"
using namespace std;

int main()
{
	int ans[101][101];//存从前一个点到后一个点的最短路径 
	for(int i = 0;i<101;i++)
	{
		for(int j = 0;j<101;j++)
		{
			ans[i][j] = INT_MAX;
		}
		ans[i][i] = 0;
	}
	
	
	int n = 0,m = 0;//n 是节点数,m是边的个数
	scanf("%d%d",&n,&m);
	for(int i = 0;i<m;i++)
	{
		int a = 0,b = 0,c = 0; 
		scanf("%d%d%d",&a,&b,&c);
		ans[a][b] = ans[b][a] = c;
	}
	//图的矩阵表示法初始化完毕后
	for(int k = 1;k<=n;k++) 
	{
		for(int i = 1;i<=n;i++)
		{
			for(int j = 1;j<=n;j++)
			{
				if(ans[i][k]==INT_MAX || ans[k][j]==INT_MAX) continue;//k的到来没有用
				if(ans[i][k]+ans[k][j]<ans[i][j]) //k的到来有用
				{
					ans[i][j] = ans[i][k] + ans[k][j];
				} 
			}
		}
	}
	printf("%d\n",ans[1][n]);
	return 0;
}

Dijkstra算法:数据结构分析dist[n]记录从初始节点到其他节点的最短路径长度,mark[n]数组标记已经计算完最短路径的节点和没有计算完最短路径的节点。算法主要步骤是新的节点的到来有没有使别的点的距离发生改变,改变的更新。之后从未知计算完最短路径长度的节点中选出一个具有最短路径的长度,作为当前的扩展节点。

#include "stdio.h" 
#include "limits.h"
#include "vector" 
using namespace std;

struct Edge
{
	int next;
	int cost;
};

int main()
{
	int n = 0,m = 0;
	while(scanf("%d%d",&n,&m))
	{
		if(n==0&&m==0) break;
		vector<Edge> edge[101];//定义的边  这个相当于头,里面存的是Edge 
		bool mark[101];//区分不能的集合
		int dist[101];
		for(int i = 0;i<101;i++)
		{
			mark[i] = false;
			edge[i].clear();
			dist[101] = INT_MAX;
		}
		
		//图存在内存中了 
		for(int i = 0;i<m;i++)
		{
			Edge e;
			int p = 0,l = 0,c = 0;
			scanf("%d%d%d",&p,&l,&c);
			e.cost = c;
			e.next = l;
			edge[p].push_back(e);
			e.next = p;
			edge[l].push_back(e);
		}
		//现在开始计算从1 到 n的路线
		int newNum = 1;
		dist[newNum] = 0;//到自己零
		mark[1] = true; 
		for(int j = 1;j<n;j++) //执行n-1次
		{
			//由于新节点的加入,到其他的是否变短
			int size = edge[newNum].size();
			for(int i = 0;i<size;i++) 
			{
				Edge e = edge[newNum][i];
				if(mark[e.next]) continue;
				if(dist[newNum]+e.cost<dist[e.next])
				{
					dist[e.next] = dist[newNum] + e.cost;
				}
			}
			//变短之后其中最短的是哪一个,将这个加入到集合中 
			int min = INT_MAX;
			 
			for(int i = 1;i<=n;i++)
			{
				if(mark[i]) continue;
				//没有加入的情况下 
				if(dist[i]<min)
				{
					min = dist[i];
					newP = i; 
				}
			}
			mark[newP] = true;
		} 
		printf("%d\n",dist[n]);
	}
	return 0;
}

SPFA:数据结构分析dist[n]存从初始节点到其他节点的最短路径,mark[n]标记是否在队列中,一个先进先出的队列,从队列中选出一个元素,通过这个节点看其他节点是否会有路径变短的情况,如果有且不在队列中,将节点加入到队列中。重复操作直到队列为空。

#include "stdio.h"
#include "queue"
#include "limits.h"
#include "vector"
using namespace std;

struct Edge{
	int next;
	int cost;
}; 

int main()
{
	int dist[101];
	bool mark[101];
	vector<Edge> e[101];
	queue<int> q;
	for(int i = 0;i<101;i++)
	{
		dist[i] = INT_MAX;
		mark[i] = false;//没有加入的数据 
		e[i].clear();
	}
	int n = 0,m = 0;
	scanf("%d%d",&n,&m);
	//初始化成功 
	for(int i = 0;i<m;i++)	
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		Edge tmp;
		tmp.cost = c;
		tmp.next = a;
		e[b].push_back(tmp);
		tmp.next = b;
		e[a].push_back(tmp);
	}
	
	q.push(1);//把第一个放进去 
	dist[1] = 0;
	mark[1] = true;
	
	while(!q.empty()) 
	{
		int top = q.front();
		q.pop();
		mark[top] = false;
		int size = e[top].size();
		
		//从当前的top节点出发的所有节点是否有缩小,有缩小的情况下加入到队列中 
		for(int i = 0;i<size;i++)
		{
			int c = e[top][i].cost;
			int next = e[top][i].next;
			if(dist[next]>dist[top]+c) 
			{
				dist[next] = dist[top] + c;	//进行缩小的操作 
				if(!mark[next])//如果不在队列中的话 
				{
					q.push(next);
					mark[next] = true; 
				}
			}
		}
	}
	printf("%d\n",dist[n]);
	return 0;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值