带权图最短路径问题

本文总结了小学期学到的算法,包括单源最短路问题的Bellman-Ford、SPFA和Dijkstra算法,以及解决任意两点间最短路的Floyd-Warshall算法。Dijkstra算法利用优先队列实现O(|E|×log|V|)的时间复杂度,Floyd-Warshall通过动态规划达到O(|V|3)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小学期学的算法和做OJ题的各种经验总结

一、单源最短路问题

  1. Bellman-Ford算法:O(|V|×|E|)
    (浪费时间,遍历每一条边的时候不知道当前边的de.from是不是正确的最短距离; 而且对于每个点都要遍历一次该点的相连边)
    从起点到第i个点的最短距离di = min{dj + wij | j与i相邻} (所有(到点i相邻的点(j)的最小距离 + 这两个点的距离)中的最小值)实现方法:存边的to, distance,初始化最短路径数组d[]为INF。按点遍历,每个点遍历一次所有的相连边。 di 就是de.to
//从起点到第i个点的最短距离di = min{d(j) + w(i,j) | j与i相邻}
// (所有(到点i相邻的点(j)的最小距离 + 这两个点的距离)中的最小值)
//实现方法:存边的to, distance,初始化最短路径数组d[]为INF,,d[起点]=0。
//按点遍历,每个点遍历一次所有的相连边。 d(i) 就是mint(d[e.to] + e.distance)
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <climits>

using namespace std;

struct edge
{
   
   
	int to, cost;
	edge(int _to, int _d) :to(_to), cost(_d) {
   
   };
};

const int MAXV = 100;//点数
vector<edge> g[MAXV];//第i个点的相连边
vector<edge>::iterator it;
int d[MAXV];
const int INF = INT_MAX;

//不判断负环的Bellman,不用
void BellmanFord(int v) {
   
   
	//s 起点
	bool update;
	do {
   
   
		update = false;
		for (int j = 1;j <= v;j++) {
   
   
			for (it = g[j].begin(); it != g[j].end(); it++) {
   
   
				edge e = *it;
				int i = e.to;
				if (d[j] != INF && d[j] + e.cost < d[i]) {
   
   
					d[i] = d[j] + e.cost;
					update = true;
				}
			}
		}
		
	} while (update);

}

//存在负圈则会经过同一个点两次
//没有负圈的话遍历完v-1个点d[v]就应该有了,如果走到v再走点v到点v的邻边比直接到v的邻边还短(会更新d[邻边])
//说明存在负环

//存在负圈返回true
bool negative_BellmanFord(int v, int start) {
   
   
	//如果d[start]为负则存在负环
	bool update;
	do {
   
   
		update = false;
		for (int j = 1; j <= v; j++) {
   
   
			for (it = g[j].begin(); it != g[j].end(); it++) {
   
   
				edge e = *it;
				int i = e.to;
				if (d[j] != INF && d[j] + e.cost < d[i]) {
   
   
					d[i] = d[j] + e.cost;
					update = true;
				}
			}
		}
		if (d[start] < 0) return true;//存在负环
	} while (update);
	return false;
}

void addEdge(const int &f, const int &t, const int &cost) {
   
   
	g[f].push_back(edge(t, cost));
}

int main() {
   
   
	////输入数据
	//无负环
	//int v = 6;
	//
	//g[1].push_back(edge(2, 5));	g[1].push_back(edge(3, 1));
	//g[2].push_back(edge(1, 5));	g[2].push_back(edge(3, 2));	g[2].push_back(edge(4, 1));
	//g[3].push_back(edge(1, 1));	g[3].push_back(edge(2, 2));	g[3].push_back(edge(4, 4));	g[3].push_back(edge(5, 8));
	//g[4].push_back(edge(2, 1));	g[4].push_back(edge(3, 4));	g[4].push_back(edge(5, 3));	g[4].push_back(edge(6, 6));
	//g[5].push_back(edge(3, 8));	g[5].push_back(edge(4, 3));
	//g[6].push_back(edge(4, 6));
	
	//有负环
	int v = 4;
	addEdge(1, 2, 1); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值