SPFA算法求固定点到其它点 最短 最长 路程问题

点击:理解请参考
例题:https://www.luogu.com.cn/problem/P1807

如果求最短路径 :vis[nex] = min(vis[nex], vis[now]+B[now][k]);
f [ ]数组你要先初始化 无穷大
即:for(int i=1; i<=n; i++) vis[i] = 999999;

如果求最长路径: vis[nex]=max(vis[nex], vis[now]+B[now][k]);
f [ ]数组你要先初始化 无穷小
即 :for(int i=1; i<=n; i++) vis[i] = 0;

还有
就是这个spfa算法跟 关键路径(拓扑) 挺像的 就稍微改改

例题正确代码:

//思路 建立两个表 位置相同 存边的长度
#include<bits/stdc++.h>
using namespace std;
vector <int> G[1515]; //存点
vector <int> B[1515]; //存边
int vis[50010]; //最大长度 
int main() 
{
	int n, m; //点数 n 边数 m 
	cin >> n >> m;
	for(int i=1; i<=m; i++)
	{
		int a, b, w; // a -> b  边的值为 w 
		cin >> a >> b >> w;
		G[a].push_back(b);
		B[a].push_back(w);
	}
	queue <int>q;
	
	q.push(1);
	
	while(!q.empty())
	{	
		//这里每次弹出来的数都是以 1号结点发散的 不在乎是否 rudp[i]== 0 
		int now = q.front();
		q.pop();
		for(int k=0; k<G[now].size(); k++)
		{
			int nex = G[now][k];
			if(vis[nex]<vis[now]+B[now][k])  
			{
				vis[nex] = max(vis[nex], vis[now]+B[now][k]);
				q.push(nex);
			}
			/-----------------------------------------------------|
			|/*如果求最短路径就是这个
			|	但是记得把 for(i<=N) vis[i] = 99999;
			|	vis[1] = 0;
			|	int nex = G[now][k];		
			|	if(vis[nex]>vis[now]+B[now][k])  
			|	{
			|		vis[nex] = min(vis[nex], vis[now]+B[now][k]);
			|		q.push(nex);
			|	}
			|*/
			/-----------------------------------------------------|
		}
	}

	if(vis[n]>0) //如果 1 能走到 n 
		cout << vis[n];
	else
		printf("-1");
		
	return 0;
}

错误代码:
错误原因:https://www.luogu.com.cn/discuss/show/300476

//思路 建立两个表 位置相同 存边的长度
#include<bits/stdc++.h>
using namespace std;
vector <int> G[1515]; //存点
vector <int> B[1515]; //存边
int rud[50010]; //存入度的数量 
int vis[50010]; //最大长度 
int ndm[5000]; //标记 1 到 n 的路径 判断走不走得到 
int main() 
{
	int n, m; //点数 n 边数 m 
	cin >> n >> m;
	for(int i=1; i<=m; i++)
	{
		int a, b, w; // a -> b  边的值为 w 
		cin >> a >> b >> w;
		G[a].push_back(b);
		B[a].push_back(w);
		rud[b]++;
	}
	ndm[1] = 1;
	queue <int>q;
	
	q.qush(1);
	while(!q.empty())
	{	//这里每次弹出来的都是按拓扑序列的  
		int now = q.front();
		q.pop();
		for(int k=0; k<G[now].size(); k++)
		{
			int nex = G[now][k];
			if(ndm[now] == 1) ndm[nex] = 1;
				
			rud[nex]--;
			if(rud[nex] == 0)  
			{
				q.push(nex);
				rud[nex]--;
			}
				
			vis[nex] = max(vis[nex], vis[now]+B[now][k]); 
			
		}
	}

	if(ndm[n] == 1 && m!=0) //如果 1 能走到 n 
		cout << vis[n];
	else
		printf("-1");
		
	return 0;
}
 //发现问题了  按拓扑序列做题不太好 应该按 bfs来广搜
 //因为 它这有影响的 拓扑序列 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言编写的程序,其中包含Dijkstra算法SPFA算法和Bellman-Ford算法解一个到其他最短距离。请注意,代码中的图是用邻接矩阵表示的。 ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> #define MAX_VERTICES 100 // 邻接矩阵表示图 int graph[MAX_VERTICES][MAX_VERTICES]; int num_vertices; // 辅助队列结构体 typedef struct { int vertex; int distance; } QueueItem; // 辅助队列 QueueItem queue[MAX_VERTICES]; int front = 0, rear = 0; void enqueue(QueueItem item) { queue[rear++] = item; } QueueItem dequeue() { return queue[front++]; } int is_queue_empty() { return front == rear; } // Dijkstra算法 void dijkstra(int start_vertex) { int distances[MAX_VERTICES]; int visited[MAX_VERTICES] = {0}; for (int i = 0; i < num_vertices; ++i) { distances[i] = INT_MAX; } distances[start_vertex] = 0; for (int count = 0; count < num_vertices - 1; ++count) { int u = -1; int min_distance = INT_MAX; // 找到当前未访问的节中距离最小的节 for (int i = 0; i < num_vertices; ++i) { if (!visited[i] && distances[i] < min_distance) { min_distance = distances[i]; u = i; } } if (u == -1) { break; } visited[u] = 1; // 更新与u相邻节的距离 for (int v = 0; v < num_vertices; ++v) { if (!visited[v] && graph[u][v] && distances[u] != INT_MAX && distances[u] + graph[u][v] < distances[v]) { distances[v] = distances[u] + graph[u][v]; } } } // 输出最短距离 printf("Dijkstra Algorithm:\n"); for (int i = 0; i < num_vertices; ++i) { printf("Vertex %d -> Vertex %d: %d\n", start_vertex, i, distances[i]); } } // SPFA算法 void spfa(int start_vertex) { int distances[MAX_VERTICES]; int in_queue[MAX_VERTICES] = {0}; for (int i = 0; i < num_vertices; ++i) { distances[i] = INT_MAX; } distances[start_vertex] = 0; enqueue((QueueItem) {start_vertex, 0}); in_queue[start_vertex] = 1; while (!is_queue_empty()) { QueueItem item = dequeue(); int u = item.vertex; in_queue[u] = 0; // 更新与u相邻节的距离 for (int v = 0; v < num_vertices; ++v) { if (graph[u][v] && distances[u] != INT_MAX && distances[u] + graph[u][v] < distances[v]) { distances[v] = distances[u] + graph[u][v]; if (!in_queue[v]) { enqueue((QueueItem) {v, distances[v]}); in_queue[v] = 1; } } } } // 输出最短距离 printf("SPFA Algorithm:\n"); for (int i = 0; i < num_vertices; ++i) { printf("Vertex %d -> Vertex %d: %d\n", start_vertex, i, distances[i]); } } // Bellman-Ford算法 void bellman_ford(int start_vertex) { int distances[MAX_VERTICES]; for (int i = 0; i < num_vertices; ++i) { distances[i] = INT_MAX; } distances[start_vertex] = 0; // 对每条边进行num_vertices - 1次松弛操作 for (int count = 0; count < num_vertices - 1; ++count) { for (int u = 0; u < num_vertices; ++u) { for (int v = 0; v < num_vertices; ++v) { if (graph[u][v] && distances[u] != INT_MAX && distances[u] + graph[u][v] < distances[v]) { distances[v] = distances[u] + graph[u][v]; } } } } // 输出最短距离 printf("Bellman-Ford Algorithm:\n"); for (int i = 0; i < num_vertices; ++i) { printf("Vertex %d -> Vertex %d: %d\n", start_vertex, i, distances[i]); } } int main() { // 初始化图 num_vertices = 5; // 邻接矩阵表示图 int adjacency_matrix[5][5] = { {0, 2, 0, 1, 0}, {2, 0, 3, 2, 0}, {0, 3, 0, 0, 1}, {1, 2, 0, 0, 4}, {0, 0, 1, 4, 0} }; for (int i = 0; i < num_vertices; ++i) { for (int j = 0; j < num_vertices; ++j) { graph[i][j] = adjacency_matrix[i][j]; } } // 调用算法最短距离 int start_vertex = 0; dijkstra(start_vertex); spfa(start_vertex); bellman_ford(start_vertex); return 0; } ``` 请注意,此程序的图是固定的,如果您希望输入不同的图,请根据需要进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值