前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用分支界限法求解Dijikstra算法

利用分支界限法求解Dijikstra算法

作者头像
AI那点小事
发布2020-04-18 00:40:13
3970
发布2020-04-18 00:40:13
举报
文章被收录于专栏:AI那点小事AI那点小事

前记

对于迪杰斯特拉算法的贪心解法请移步:最短路径算法(上)——迪杰斯特拉(Dijikstra)算法

算法流程

1 初始化最小堆q,距离数组dist全为无穷大,collected数组为全0,path数组全为-1,dist[i]代表顶点i到源顶点的最短距离,最小堆按照dist的大小进行排序,源顶点为s,dist[s]=0。源顶点s加入最小堆。Collected[i]代表顶点i是否加入最小堆,0代表未收录,1代表收录。path[i]代表顶点i最短路径上的中间顶点,其中-1代表源顶点。 2 从最小堆中弹出堆顶元素start,之后遍历(bfs)相邻结点i,若start和i之间的权重G[start][i]+dist[start]<dist[i],那么dist[i]=G[start][i]+dist[start]。并且将i加入最小堆。 3 最小堆不为空时,循环执行步骤2


C++代码

代码语言:javascript
复制
#include <iostream>
#include <cstring>
#include <stack>
#include <queue> 
#include <vector> 
using namespace std;

const int MAX = 65535;
int G[1001][1001];
int dist[1001] = {0};
int path[1001] = {0};
int visited[1001] = {0};
int Nv,Ne;
int start;

struct cmp{
	bool operator()(int &a,int &b){
		return dist[a]>dist[b];
	}
};

void Create_Graph()
{
	//初始化距离数组为正无穷 
	for(int i = 0 ; i < 1001 ; i++){
		dist[i] = MAX;
	}
	//初始化路径数组为-1 
	memset(path,-1,sizeof(path[0])*(1001));
	//初始化访问数组为-1 
	memset(visited,0,sizeof(visited[0])*(1001));
	//memset(this->collected,0,sizeof(this->collected[0])*(nv+1));
	for(int i = 0 ; i < 1001 ; i++){
		for(int j = 0 ; j < 1001 ; j++){
			G[i][j] = MAX;	
		}
	}
	//初始化图
	cout<<"请输入顶点数与边数:"<<endl; 
	cin>>Nv>>Ne;
	cout<<"请输入边与权重:"<<endl;
	for(int i = 0 ; i < Ne ; i++){
		int v1,v2,weight;
		cin>>v1>>v2>>weight;
		G[v1][v2] = G[v2][v1] = weight;
	}	
}

//迪杰斯特拉算法 
bool Dijikstra(int vertex)
{
	priority_queue<int,vector<int>,cmp> q;
	//源顶点加入最小堆 
	q.push(vertex);
	//初始化源顶点的dist为0 
	dist[vertex] = 0;
	visited[vertex] = 1; 
	//最小堆不为空,一直循环 
	while(!q.empty()){
		//从最小堆中弹出最小元素 
		int start = q.top();
		q.pop();
		for(int i = 1 ; i < Nv+1 ; i++){
			//负值圈问题 
			if(G[start][i] < 0){
				return false;
			}
			// bfs遍历领接结点 
			if (G[start][i] < MAX){
				if(visited[i] == 0){
					// i到start的最小距离大于dist[start]+G[start][i]
					if(dist[i] > dist[start] + G[start][i]){
						dist[i] = dist[start] + G[start][i];
						q.push(i);
						path[i] = start;
					}	
				}	
			}
		}
	}
	return true;
}

//打印start到end的最短路径 
void Print(int start ,int end)
{
	stack<int> stack;
	stack.push(end);
	cout<<start<<"到"<<end<<"的最短路径为:";
	int j = end;
	while(path[j] != -1){//路径上的元素一次入栈 
		j = path[j];
		stack.push(j);	
	}
	//打印路径 
	cout<<stack.top();
	stack.pop(); 
	while(!stack.empty()){
	cout<<" -> "<<stack.top();
	stack.pop();
	}
	cout<<"\n"<<"最短路径长度为:"<<dist[end]<<endl;
}

void Print_Dijikstra(int vertex)
{
	for(int i = 1 ; i < Nv+1 ; i++){
		if(i == vertex){
			continue;
		} 
		Print(vertex,i); 
	}
}


int main() 
{
	Create_Graph();
	cout<<"请输入一个起始点:"<<endl;
	int vertex;
	cin>>vertex;
	if(Dijikstra(vertex)){
		Print_Dijikstra(vertex); 	
	}
	
	return 0;
}

例子

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前记
    • 算法流程
      • C++代码
        • 例子
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档