C++算法入门练习——最短路径-多路径

现有一个共n个顶点(代表城市)、m条边(代表道路)的无向图(假设顶点编号为从0n-1),每条边有各自的边权,代表两个城市之间的距离。求从s号城市出发到达t号城市的最短路径条数和最短路径(可能有多条)。

解题思路:

Dijkstra算法的改进。

由于这里最短路径有可能有多个,因此单纯设置一个pre数组记录结点的父亲结点行不通。而也给出了解决方法,改用vector可变数组。

当我们遇见du+Guj.weight<dnewv时候,

需要对之前的prenewv进行清空,重新存放。

而遇见du+Guj.weight==dnewv时,只需把这个新的路径结点也加入即可。

而后我们要遍历这个pre,当到达递归边界(v==s)时候,把路径加入到结果paths中保存,然后temppath弹出,继续寻找其他的路径。

而这个存储的是逆序,我们需要对每一条路径做一次逆序,然后再进行排序,从而进行输出。

完整代码如下:

cpp 复制代码
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int INF = 1000000000;
const int maxn = 101;
int n,t;

struct node{
	int v;
	int weight;
}; 

vector<node> G[maxn]; 
bool isvisited[maxn] = {false};
int d[maxn];
vector<int> pre[maxn];

void Dijkstra(int v){
	fill(d,d+maxn,INF);
	d[v] = 0;
	for(int i=0;i<n;i++){
		int u = -1,min = INF;
		for(int j=0;j<n;j++){
			if(!isvisited[j]&&d[j]<min){
				u = j;
				min = d[j];
			}
		}
		if(u==-1){
			return ;
		}
		isvisited[u] = true;
		for(int j=0;j<G[u].size();j++){
			int newv = G[u][j].v;
			if(!isvisited[newv]){
				if(d[u]+G[u][j].weight<d[newv]){
					pre[newv].clear();
					d[newv] = d[u]+G[u][j].weight;
					pre[newv].push_back(u);
				}
				else if(d[u]+G[u][j].weight==d[newv]){
					pre[newv].push_back(u);
				}
			}
		}
	}
}

vector<vector<int>> paths;
vector<int> temppath;

void minpath(int s,int v){
	if(v==s){
		temppath.push_back(v);
		paths.push_back(temppath);
		temppath.pop_back();
		return;
	}
	temppath.push_back(v);
	for(int i=0;i<pre[v].size();i++){
		minpath(s,pre[v][i]);	
	}
	temppath.pop_back();
}

int main(){
	int m,s;
	cin>>n>>m>>s>>t;
	int a,b,w;
	for(int i=0;i<m;i++){
		cin>>a>>b>>w;
		node temp;
		temp.v = b;
		temp.weight = w;
		G[a].push_back(temp);
		temp.v = a;
		G[b].push_back(temp);
	}
	Dijkstra(s);
	minpath(s,t);
	cout<<paths.size()<<endl;
	for (int i = 0; i < paths.size(); i++) {
        reverse(paths[i].begin(), paths[i].end());
    }
    sort(paths.begin(), paths.end());
	for(int i=0;i<paths.size();i++){
		for(int j=0;j<paths[i].size();j++){
			if(j!=0){
				cout<<"->";
			}
			cout<<paths[i][j];
		}
		cout<<endl;
	}
	return 0;
}
相关推荐
CRMEB系统商城21 分钟前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
王维同学1 小时前
[自学][Windows C++]RunOnceEx 注册表分组键的安全遍历
c++·windows·安全·开源
keyipatience1 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
我的xiaodoujiao2 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
战族狼魂2 小时前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
李剑一2 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH2 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
爱喝水的鱼丶2 小时前
SAP-ABAP:ALV通用封装实践——搭建可复用的ALV开发工具类,减少80%重复代码
开发语言·性能优化·sap·abap·erp·alv
脱胎换骨-军哥2 小时前
C++/Rust无缝互操作:混合系统新常态
开发语言·c++·rust
songroom3 小时前
Kimi K3:Rust封装XTP接口详细教程实践
开发语言·后端·rust