1.单源最短路径
1.Bellman-ford(可以判断负环 处理负权)
void bellman(int cur) {
for (int i = 1; i <= n; i++) dis[i] = INF;
dis[1] = 0;
for (int i = 0; i < m; i++)
{
memcpy(backup, dis, sizeof dis);
for (int j = 0; j < edge.size(); j++)
{
int a = edge[j].first, b = edge[j].second, c = 1;
dis[b] = min(dis[b], backup[a] + c);
}
}
}
2.spfa(可以判断负环 处理负权)
void spfa(int cur){
for (int i = 0; i <= n; i++){
dis[i] = INF; vis[i] = 0; }
dis[cur] = 0;
queue<int> q;
q.push(cur);
while (!q.empty()){
int top = q.front(); q.pop();
vis[top] = 0;
for (auto &point : e[top]){
int nx = point.first, v = point.second;
if (dis[nx] > dis[top] + v){
dis[nx] = dis[top] + v;
if (!vis[nx]){
vis[nx] = 1;
q.push(nx);
}
}
}
}
}
3.dijkstra算法(只能处理正权)
void dijkstra(int cur){
for (int i = 0; i <= n; i++){
dis[i] = INF; vis[i] = 0; }
dis[cur] = 0;
priority_queue<PII, vector<PII>, greater<PII>> q;
q.push({
0,cur});
while (!q.empty()){
int top = q.top().second; q.pop();
if (vis[top])continue;
vis[top] = 1;
for (auto &point : e[top]){
int nx = point.first, v = point.second;
if (!vis[nx] && dis[nx] > dis[top] + v){
dis[nx] = dis[top] + v;
q.push({
dis[nx],nx});
}
}
}
}
2.多源最短路径
1.Floyd (处理负权)
void floyd() {
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
}
2.Johnson
Johnson 算法则通过一种方法来给每条边重新标注边权。
我们新建一个虚拟节点(在这里我们就设它的编号为 0)。从这个点向其他所有点连一条边权为 0 的边。
接下来用 Bellman-Ford 算法求出从 0 号点到其他所有点的最短路,记为 h i h_i hi
假如存在一条从 u 点到 v 点,边权为 w 的边,则我们将该边的边权重新设置为 w + h u − h v w + h_u - h_v w+hu−hv 。
接下来以每个点为起点,跑 n 轮 Dijkstra 算法即可求出任意两点间的最短路了。
那这么说,Dijkstra 也可以求出负权图(无负环)的单源最短路径了?
对于任意一点 ( u , v ) (u,v) (u,v), 根据三角不等式, h v < h u + w ( u , v ) h_v < h_u + w(u,v) hv<hu+w(u,v)
w ′ ( u , v ) = w ( u , v ) + h u − h v ≥ 0 w^{'}(u,v)=w(u,v) + h_u - h_v \geq 0 w′(u,v)=w(u,v)+hu−hv≥0
P5905 【模板】Johnson 全源最短路
#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <chrono>
#include <ctime>
#include <cmath>
#include <cctype>
#include <string>
#include <cstdio>
#include <iomanip>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iterator>
using namespace std;
//void rfIO()
//{
// FILE *stream1;
// freopen_s(&stream1,"in.txt", "r", stdin);
// freopen_s(&stream1,"out.txt", "w", stdout);
//}
inline void read(int &x){
x = 0;
char ch = getchar(); int f = 1;
while (!isdigit(ch) && ch^'-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
x *= f;
}
static auto speedup = [](){
ios::sync_with_stdio(false); cin.tie(); cout.tie(); return nullptr; }();
typedef long long int ll;
typedef pair<int, ll> PII;
const int maxn = 3e3 + 7,INF = 1e9;
ll n, m,vis[maxn],tcnt[maxn],dis[maxn],d[maxn];
vector<PII> matrix[maxn];
bool spfa(int s){
for (int i = 1; i <= n; i++)d[i] = INF, vis[i] = 0;
d[s] = 0; vis[s] = 1;
queue<int> q;
q.push(s);
while (!q.empty()){
int top = q.front();
q.pop();
vis[top] = 0;
for (int i = 0; i < matrix[top].size(); i++){
PII pi = matrix[top][i];
int nx = pi.first, w = pi.second;
if (d[nx] > d[top] + w){
if (!vis[nx]){
if (++tcnt[nx] >= n + 1) return false;
d[nx] = d[top] + w;
q.push(nx);
vis[nx];
}
}
}
}
return true;
}
void dijkstra(int s){
for (int i = 1; i <= n; i++)dis[i] = INF;
memset(vis, 0, sizeof(vis));
dis[s] = 0;
priority_queue<PII, vector<PII>, greater<PII>> q;
q.push({
0, s });
while (!q.empty()){
int top = q.top().second; q.pop();
if (vis[top])continue;
vis[top] = 1;
for (int i = 0; i < matrix[top].size(); i++){
PII pi = matrix[top][i];
int nx = pi.first, w = pi.second;
if (dis[nx] > dis[top] + w){
dis[nx] = dis[top] + w;
q.push({
dis[top] + w,nx });
}
}
}
}
int main()
{
int x, y, z;
cin >> n >> m;
for (int i = 1; i <= m; i++){
cin >> x >> y >> z;
matrix[x].push_back({
y, z });
}
for (int i = 1; i <= n; i++){
matrix[n + 1].push_back({
i,0});
}
if (!spfa(n + 1)){
cout << -1 << endl;
return 0;
}
for (int i = 1; i <= n; i++){
for (int j = 0; j < matrix[i].size(); j++){
int a = i, b = matrix[i][j].first,w = matrix[i][j].second;
matrix[i][j].second += d[a] - d[b];
}
}
for (int i = 1; i <= n; i++){
dijkstra(i);
long long ans = 0;
for (int j = 1; j <= n; j++)
{
if (dis[j] == INF) ans += 1ll * j*INF;
else ans += 1ll * j*(dis[j] + (d[j] - d[i]));
}
printf("%lld\n", ans);
}
return 0;
}