算法笔记:图论单源最短路

求解所有两点间的最短路的问题叫做任意任意两点间的最短路问题。

Floyed-Warshall算法

类似dp思想的一种最短路算法

时间复杂度

\(O(n^{3})\)

处理限制

  • 可以处理边权为负的情况

  • 可以判断图中是否有负圈

  • 时间复杂度过高

代码

LuoGu P3371 【模板】单源最短路径

//#define fre yes

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 256+10;
int d[maxn][maxn];

int n,m,t;

template<typename T>inline void read(T&x)
{
    x = 0;char c;int lenp = 1;
    do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
    do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
    x *= lenp;
}

void floyd(int x)
{
    for (int k=1;k<=x;k++)
    {
        for (int i=1;i<=x;i++)
        {
            for (int j=1;j<=x;j++)
            {
                d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
            } } }
}

int main()
{
    memset(d,0x3f3f3f3f,sizeof(d));
    read(n);read(m);read(t);
    for (int i=1;i<=m;i++)
    {
        int x,y,z;
        read(x);read(y);read(z);
        d[x][y] = z;
    } floyd(n);
    for (int i=1;i<=n;i++) { if(t == i) { printf("0 ");continue; }printf("%d ",d[t][i]); }
    return 0;
}

####Shortest Path Faster Algorithm (Spfa)算法 最短路径最快的算法(开玩笑)

类似广度优先搜索

时间复杂度

\(O(VE)\)

V:顶点数
E:边数

处理限制

  • 可以处理边权为负的情况

  • 可以判断图中是否有负圈

  • 时间复杂度低,但容易被卡

代码

LuoGu P3371 【模板】单源最短路径

//#define fre yes

#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 256+10;
int head[maxn];
int edge[maxn];
int ver[maxn];
int to[maxn];

int inq[maxn];
int d[maxn];

int n,m,t,tot;

template<typename T>inline void read(T&x)
{
    x = 0;char c;int lenp = 1;
    do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
    do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
    x *= lenp;
}

void addedge(int x,int y,int z)
{
    edge[tot] = z;
    ver[tot] = y;
    to[tot] = head[x];
    head[x] = tot++;
}

void spfa(int x)
{
    queue<int> q;

    q.push(x);
    d[x] = 0; inq[x] = 1;
    while(!q.empty())
    {
        int now = q.front();q.pop();
        for (int i=head[now];~i;i=to[i])
        {
            int v = ver[i];
            if(d[v] > d[now] + edge[i])
            {
                d[v] = d[now] + edge[i];
                if(inq[v] == 1) continue;
                inq[v] = 1;
                q.push(v); 
            }
        }
    }
}

int main()
{
    memset(d,0x3f3f3f3f,sizeof(d));
    memset(head,-1,sizeof(head));

    read(n);read(m);read(t);
    for (int i=1;i<=m;i++)
    {
        int x,y,z;
        read(x);read(y);read(z);
        addedge(x,y,z);
    } spfa(t);

    for (int i=1;i<=n;i++) printf("%d ",d[i]);
    return 0;
}

####Dijkstra单源最短路算法

类似广度优先搜索

时间复杂度

如果Spfa是\(O(V^{2})\)
那么Dij就是\(O(Vlog_{E})\)

处理限制

  • 不能处理负权的情况

  • 速度比Spfa要快点

  • 考试一般不卡

代码

LuoGu P3371 【模板】单源最短路径

//#define fre yes

#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 256+10;
int head[maxn];
int edge[maxn];
int ver[maxn];
int to[maxn];

int d[maxn];

int n,m,t,tot;

template<typename T>inline void read(T&x)
{
    x = 0;char c;int lenp = 1;
    do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
    do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
    x *= lenp;
}

void addedge(int x,int y,int z)
{
    edge[tot] = z;
    ver[tot] = y;
    to[tot] = head[x];
    head[x] = tot++;
}

void Dijkstra(int x)
{
    priority_queue<pair<int,int> > q;

    d[x] = 0;
    q.push(make_pair(-d[x],x));
    while(!q.empty())
    {
        int now = q.top().second;q.pop();
        for (int i=head[now];~i;i=to[i])
        {
            int v = ver[i];
            if(d[v] > d[now] + edge[i])
            {
                d[v] = d[now] + edge[i];
                q.push(make_pair(-d[v],v)); 
            }
        }
    }
}

int main()
{
    memset(d,0x3f3f3f3f,sizeof(d));
    memset(head,-1,sizeof(head));

    read(n);read(m);read(t);
    for (int i=1;i<=m;i++)
    {
        int x,y,z;
        read(x);read(y);read(z);
        addedge(x,y,z);
    } Dijkstra(t);

    for (int i=1;i<=n;i++) printf("%d ",d[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/Steinway/p/9211704.html