浅(瞎)谈(吹)最短路径算法总结(Floyd,Bellmen-ford,Dijkstra,Spfa)——————《最短路·终章》

浅(瞎)谈(吹)最短路径算法总结(Floyd,Bellmen-ford,Dijkstra,Spfa)——————《最短路·终章》

V:点数
E : 边数

Dijkstra

:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度
O(E+V log V)

Bellman-Ford

:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE)

基本标程 AC Pascal代码:

var
        n,m,x,y,i,j,bj:longint;
        a,b,c,dis:array[-10005..1000005] of longint;
begin
        readln(n,m,x,y);
        for i:=1 to m do
                readln(a[i],b[i],c[i]);
        for i:=1 to n do
                dis[i]:=maxlongint div 2;
        dis[x]:=0;
        for i:=1 to n-1 do
        begin
                bj:=0;
                for j:=1 to m do
                begin
                        if dis[b[j]]>dis[a[j]]+c[j] then
                        begin
                                dis[b[j]]:=dis[a[j]]+c[j];
                                bj:=1;
                        end;
                        if dis[a[j]]>dis[b[j]]+c[j] then
                        begin
                                dis[a[j]]:=dis[b[j]]+c[j];
                                bj:=1;
                        end;
                end;
                if bj=0 then
                        break;
        end;
        writeln(dis[y]);
end.

附上AC C++代码:

#include <cstdio>
#include <iostream>

using namespace std;

bool bj;
int n,m,x,y,i,j,a[1000005],b[1000005],c[1000005],dis[1000005];
int main()
{
	scanf("%d%d%d%d",&n,&m,&x,&y);
	for (i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a[i],&b[i],&c[i]);
	}
	for (i=1;i<=n;i++)
	{
		dis[i]=100000005;
	}
	dis[x]=0;
	for (i=1;i<=(n-1);i++)
	{
		bj=false;
		for (j=1;j<=m;j++)
		{
			if (dis[b[j]]>dis[a[j]]+c[j])
			{
				dis[b[j]]=dis[a[j]]+c[j];
				bj=true;
			}
			if (dis[a[j]]>dis[b[j]]+c[j])	
			{
				dis[a[j]]=dis[b[j]]+c[j];
				bj=true;
			}
		}
		if (bj==false)
		{
			break;
		}
	}
	printf("%d",dis[y]);
	return 0;
}

SPFA(Bellman-Ford优化)

:适用于权值有负值,且没有负圈的图的单源最短路径,论文中的复杂度O(kE),k为每个节点进入Queue的次数,且k一般<=2,但此处的复杂度证明是有问题的,其实SPFA的最坏情况应该是O(VE).

Floyd

:每对节点之间的最短路径。多元最短路径,适用于权值为正负都可,O(n^3).
基本标程 AC Pascal代码:

var
        n,m,i,j,k,a,b,ans,max:longint;
        map:array[1..1005,1..1005]of int64;
begin
        readln(n,m);
        for i:=1 to n do
                for j:=1 to n do
                        map[i,j]:=maxlongint;
        for i:=1 to m do
        begin
                readln(a,b,ans);
                map[a,b]:=ans;
                map[b,a]:=ans;
        end;
        for k:=1 to n do
                for i:=1 to n do
                        for j:=1 to n do
                                if map[i,k]+map[k,j]<map[i,j] then
                                        map[i,j]:=map[i,k]+map[k,j];
        max:=-maxlongint;
        for i:=1 to n do
                if (map[1,i]<>maxlongint) and (map[1,i]>max) then
                        max:=map[1,i];
        writeln(max);
end.


附上AC C++代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#include<set>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 101
#define MOD 123
#define E 1e-6
using namespace std;
int g[N][N];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)
                g[i][j]=0;
            else
                g[i][j]=INF;
        }
    }
    for(int i=1;i<=m;i++)
    {
        int x,y,w;
        cin>>x>>y>>w;
        g[x][y]=w;
        g[y][x]=w;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(g[i][j]>g[i][k]+g[k][j])
                    g[i][j]=g[i][k]+g[k][j];
    int maxx=-INF;
    for(int i=1;i<=n;i++)
        if(g[1][i]>maxx)
            maxx=g[1][i];
    if(maxx==INF)
        cout<<"-1"<<endl;
    else
        cout<<maxx<<endl;
    return 0;
}

《最短路·完》!

发布了21 篇原创文章 · 获赞 26 · 访问量 7669

猜你喜欢

转载自blog.csdn.net/NGoairpy/article/details/104031114
今日推荐