Dijkstra算法----解决最短路径问题

这篇文章利用图解的方式讲得十分清楚,可惜他的代码太乱了,看不懂,自己写了一份简单的。

https://blog.csdn.net/qq_35644234/article/details/60870719?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164637716116780264050431%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164637716116780264050431&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-60870719.pc_search_result_control_group&utm_term=dijkstra%E7%AE%97%E6%B3%95&spm=1018.2226.3001.4187https://blog.csdn.net/qq_35644234/article/details/60870719?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164637716116780264050431%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164637716116780264050431&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-60870719.pc_search_result_control_group&utm_term=dijkstra%E7%AE%97%E6%B3%95&spm=1018.2226.3001.4187

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N=1e3+5;
int ma[N][N],vis[N];
struct node{
	int value;
	string path;
}dis[N]; 
int n,m;
void dijkstra()
{
	int i,j;
	for(i = 1;i <= n-1; i++){
		int mint = INF;
		int min_design;
		//寻找这一层权值最小的点
		 for(j = 1;j <= n; j++){
		 	if(vis[j] == 0 && dis[j].value < mint){
		 		mint = dis[j].value;
		 		min_design = j;
			 }
		 }
		 vis[min_design] = 1;
		 
		 for(j = 1;j <= n; j++){
		 	//对于每个可以到达的j
			 if(ma[i][j] < INF){
			 	//如果可以找到更小的到j点的方法,那就更新 
			 	if(dis[j].value > dis[i].value+ma[i][j]){
			 		dis[j].value = dis[i].value + ma[i][j];
			 		dis[j].path = dis[j].path + "-->v"+to_string((i+1)); 
				 }
			 } 
		 }
	}
}
void path(int begin);
int main()
{
	scanf("%d%d",&n,&m);
	int i,j;
	for(i = 1;i <= n; i++){//初始化 
		for(j = 1;j <=n; j++){
			if(i == j) ma[i][j] = 0;
			else ma[i][j] = INF;
		}
	}
	for(i = 1;i <= m; i++){
		int x1,x2,y;
		scanf("%d%d%d",&x1,&x2,&y);
		ma[x1][x2] = y;
		ma[x2][x1] = y;
	}
	for(i = 1;i <= n; i++){
		dis[i].value = ma[1][i];//从点1可以达到的点,存入dis 
		dis[i].path = "v" + to_string(1) + "-->" +to_string(i+1);
	} 
	vis[1] = 1;
	dijkstra();
	for(i = 1;i <= n; i++){
		cout<<dis[i].value<<" ";
	}cout<<"\n";
	path(1);
	return 0;
}
void path(int begin)
{
	string str;
	str = "v"+ to_string(begin);
	printf("以%s为起点的图的最短路径为:",str.c_str());
	for(int i = 0;i != n;i++){
		if(dis[i].value != INF){
			cout<< dis[i].path << "=" << dis[i].value <<"\n";
		}else{
			cout<< dis[i].path <<"是无最短路径的"<<"\n";
		}
	}
}
/*
	6 8
1 3 10
1 5 30
1 6 100
2 3 5
3 4 50
4 6 10
5 6 60
5 4 20
*/

Decv++ 不支持c++11标准,所以用to_string时需要在编译器加入如上指令;

加强例题:紧急救援

https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840icon-default.png?t=M1L8https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840

#include<bits/stdc++.h>
using namespace std;
#define INF 1e9+7
const int N = 1005;
int ma[N][N];
int army[N];//每个城市的军队
int added[N];//标志该点是否已经加入了最短路径集合
int distanced[N];//用于记录到当前点的长度
int path[N];//用于保存最短路径,前驱
int pathNum[N];//统计到当前点有多少种不同的路径
int armyNum[N];//统计到当前点已经集合了多少军队
int n,m,s,d;
void initial();
void dijkstra();
int main()
{
	cin>>n>>m>>s>>d;
	int i,j;
	initial();
	dijkstra();
	printf("%d %d\n",pathNum[d],armyNum[d]);
	i = d;
	int p[N];
	int count = 0;
	while(i != s){
		p[count++] = i;
		i = path[i];
	}
	for(i = count;i >= 0; i--){
		if(i == count){
			printf("%d",s);
		}else{
			printf(" %d",p[i]);
		}
	}
	printf("\n");
} 
void initial()
{
	int i,j;
	for(i = 0;i < n; i++) cin>>army[i];
	for(i = 0;i < n; i++){
		for(j = 0;j < n; j++){
			ma[i][j] = INF;
		}
	}
	for(i = 0;i < m; i++){
		int x,y,len;
		cin>>x>>y>>len;
		ma[x][y] = ma[y][x] = len;
	}
}
void dijkstra()
{
	int i,j;
	for(i = 0;i < n; i++){//初始化所有; 
		added[i] = 0;
		path[i] = s;
		distanced[i] = ma[s][i];//s点到i点 
		pathNum[i] = 1;
		armyNum[i] = army[s] + army[i];
	}
	//取出第一个点 
	added[s] = 1;
	distanced[s] = 0;
	path[s] = s;
	pathNum[s] = 1;
	armyNum[s] = army[s];
	//循环讲其余n-1个点一次选取从s到v路径最短的那个点加入到 
	//是最短路径的集合种,并更新对应的状态
	for(i = 1;i <=n-1 ; i++){
	 	int min_distanced = INF;
	 	int v;//前驱
		for(j = 0;j < n; j++){
			if(added[j] == 0 && min_distanced>distanced[j]){
		 		v = j;
		 		min_distanced = distanced[j];
			}
		}
		added[v] = 1;//找到最小的
		for(j = 0;j < n; j++){
			if(added[j] != 0) continue;
			if(distanced[j] > distanced[v] + ma[v][j]){
				distanced[j] = distanced[v] +ma[v][j];
				path[j] = v;//路径添加
				pathNum[j] = pathNum[v];
				armyNum[j] = armyNum[v] + army[j]; 
			}
			else if(distanced[j] == distanced[v]+ma[v][j]){
				pathNum[j] += pathNum[v];
				//路径长度相等情况比军队数量
				if(armyNum[j] < armyNum[v]+army[j]){
					armyNum[j] = armyNum[v] + army[j];
					path[j] = v;
				} 
			}
		} 
	}
	 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值