Yen 的k_shortest paths 算法的C++实现

博客详细介绍了Yen的k_shortest_paths算法,并提供了C++实现。作者分享了对算法的理解,虽然可能不完全准确,但整体数据结构和逻辑正确。文章中指出,算法有待改进的地方是未使用堆优化,作者计划后续改进。
摘要由CSDN通过智能技术生成

具体介绍见:https://en.wikipedia.org/wiki/Yen%27s_algorithm

还有具体步骤见:https://blog.csdn.net/sharpdew/article/details/446510?tdsourcetag=s_pctim_aiomsg

我也不知道我对这个算法理解是否完全正确,但是大体的数据结构和逻辑是正确的,希望大家指点,后期我更理解了,会做相应修改。

在这个算法里需要改进的地方是:我没有用堆去插入,这个等有时间再做 

#include<vector>
#include<string>
#include<math.h>
#include<algorithm>
#include <iostream>
#include<stack>
using namespace std;
static const unsigned int INF(std::numeric_limits<int>::max());
static const unsigned undefined = INF;

class K_Shortest_Path {
public:
	vector<vector<unsigned int>> run(
		const unsigned int kPath,					// K Path
		const vector<vector<unsigned int>>& NW,		// network
		const unsigned int src,						// source node
		const unsigned int dst);					// destination node
};


//
//结构体用于保存两点之间的最短路径和长度
//
class DijPath
{
public:
	vector<unsigned int> onePath;
	int cost;

	bool operator <(const DijPath &n2);

	//判断两条路径是否相等
	bool operator ==(const DijPath &n2);
};


bool DijPath::operator <(const DijPath &n2)
{
	return cost < n2.cost;
}
//判断两条路径是否相等
bool DijPath::operator ==(const DijPath &n2)
{
	if (onePath.size() == n2.onePath.size())
	{
		for (unsigned int i = 0; i < onePath.size(); i++)
		{
			if (onePath[i] != n2.onePath[i])
				return false;
		}

		return true;
	}

	return false;
}


//
//最短路径算法,返回一个DijPath结构体
//
DijPath dijkstra(
	const vector<vector<unsigned int>> &NW,
	const int src,
	const int dst
)
{
	//图中节点个数
	unsigned int sizeNW = NW.size(); 

	//知道每一个节点都被访问过结束
	vector<bool> visited(sizeNW); 

	//到达dst顶点的最短路径的前一个顶点
	vector<unsigned int> prev(sizeNW);    

	//下一个距离当前访问过的最小的一个点
	int minPos = 0; 

	//用于记录每个顶点到源节点的距离,如果最终len[dst]=INF,
	//说明src和dst不可到达,讲cost设置为INF,用于ksp做判断舍弃这条路径
	vector<unsigned int> len(sizeNW);

	for (unsigned int i = 0; i < NW.size(); i++) //初始化
	{
		visited[i] = false;  //一开始均被访问
		len[i] = NW[src][i];
		prev[i] = INF;
	}

	//初始节点被设置为访问过
	visited[src] = true;

	for (unsigned int i = 0; i < sizeNW; ++i)  
	{
		unsigned int min = INF;      //记录访问过的节点到没访问过的节点的最小路径长度

		for (unsigned int j = 0; j < sizeNW; ++j)
		{
			if (!visited[j] && min > len[j])
			{
				minPos = j;   //记录找到了下一个节点
				min = len[j];
			}
		}

		visited[minPos] = true;

		for (unsigned int j = 0; j < sizeNW; ++j)
		{
			//如果j节点没有被访问过,且通过j节点发现到其他节点更短的len[j]值
			if (!visited[j] && len[j] > (len[minPos] + NW[minPos][j]))
			{
				prev[j] = minPos;
				len[j] = len[minPos] + NW[minPos][j];
			}
		}
	}

	
	unsigned int beforeVertex = dst;
	//通过一个栈将prev[]中的节点给倒过去,实现正序排列
	stack<unsigned int> st;
	while (prev[beforeVertex] != IN
下面是使用 Yen算法求K短路的C++代码。其中,我们使用了Dijkstra算法作为最短路径算法实现。 ```c++ #include <iostream> #include <vector> #include <queue> #include <algorithm> #include <cstring> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 100005; const int MAXM = 500005; struct Edge { int to, next, w; } edge[MAXM]; int head[MAXN], edgeNum; int dis[MAXN], vis[MAXN], pre[MAXN]; int n, m, k; void addEdge(int u, int v, int w) { edge[edgeNum].to = v; edge[edgeNum].w = w; edge[edgeNum].next = head[u]; head[u] = edgeNum++; } void dijkstra(int s) { priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq; memset(dis, INF, sizeof(dis)); memset(vis, 0, sizeof(vis)); memset(pre, -1, sizeof(pre)); dis[s] = 0; pq.push(make_pair(dis[s], s)); while (!pq.empty()) { int u = pq.top().second; pq.pop(); if (vis[u]) continue; vis[u] = 1; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (dis[v] > dis[u] + edge[i].w) { dis[v] = dis[u] + edge[i].w; pre[v] = u; pq.push(make_pair(dis[v], v)); } } } } vector<int> Astar(int s, int t, int k) { priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq; vector<int> res; if (s == t) return res; pq.push(make_pair(0, s)); int cnt = 0; while (!pq.empty()) { cnt++; if (cnt > 1000000) break; int g = pq.top().first; int u = pq.top().second; pq.pop(); if (u == t) { res.push_back(g); if (res.size() == k) return res; } for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v == pre[u]) continue; pq.push(make_pair(g + edge[i].w + dis[v] - dis[u], v)); } } return res; } void Yen(int s, int t, int K) { vector<vector<int> > paths(K, vector<int>()); vector<int> candidates; dijkstra(s); if (dis[t] == INF) return; candidates = Astar(s, t, 1); for (int k = 0; k < K && !candidates.empty(); k++) { int w = candidates.back(); candidates.pop_back(); paths[k].push_back(s); for (int i = t; i != -1; i = pre[i]) paths[k].push_back(i); reverse(paths[k].begin(), paths[k].end()); for (int i = 0; i < paths[k].size() - 1; i++) { int u = paths[k][i]; int v = paths[k][i + 1]; for (int j = head[u]; j != -1; j = edge[j].next) { if (edge[j].to == v && edge[j].w == w) { edge[j].w = INF; break; } } } dijkstra(s); candidates = Astar(s, t, 1); } for (int i = 0; i < K; i++) { if (paths[i].empty()) break; cout << "Path " << i + 1 << ": "; for (int j = 0; j < paths[i].size(); j++) cout << paths[i][j] << " "; cout << endl; } } int main() { memset(head, -1, sizeof(head)); cin >> n >> m >> k; for (int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; addEdge(u, v, w); } Yen(1, n, k); return 0; } ``` 其中,dijkstra()函数是使用堆优化的Dijkstra算法实现,Astar()函数是A*算法实现Yen()函数是Yen算法的具体实现。在Yen()函数中,我们首先使用Dijkstra算法求出起点到终点的最短路径,并使用A*算法求出第一条最短路,然后对于每条路径,我们找出其路径上的边,并将其权值设为无穷大,再次使用Dijkstra算法求出起点到终点的最短路径,并使用A*算法求出新的最短路。重复上述步骤,直到找到K条不同的最短路或者无法找到更多的可行路径为止。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值