最短路模板(Floyd && Dijkstra优化 && Bellman-Ford && spfa优化)

1.Floyd

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+50;
const int inf=0x3f3f3f3f;
int g[N][N],n,m;
void floyd()
{
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
         ///必要时剪枝
         ///if(g[i][k]<inf)
            for(int j=1;j<=n;j++)
                g[i][j]=min(g[i][k]+g[k][j],g[i][j]);
        }
    }
}
int main()
{
    int a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF&&n&&m)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                g[i][j]=inf;
        }
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(c<g[a][b])
                g[a][b]=g[b][a]=c;
        }
        floyd();
        cout<<g[1][n]<<'\n';
    }
    return 0;
}

 (/▽\) 新加~floyd对无向图的优化 https://blog.csdn.net/lanshuizhiyun/article/details/77864648

2.Dijkstra

<1>朴素版

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+50;
const int inf=0x3f3f3f3f;
int g[N][N],dis[N],vis[N];
int n,m;
void dijk()
{
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
        dis[i]=g[1][i];
    vis[1]=1;
    dis[1]=0;
    for(int i=1;i<=n;i++)
    {
        int pos,minn=inf;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&minn>dis[j])
            {
                pos=j;
                minn=dis[j];
            }
        }
        vis[pos]=1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&dis[j]>dis[pos]+g[pos][j])
                dis[j]=dis[pos]+g[pos][j];
        }
    }
}
int main()
{
    int a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF&&n&&m)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                g[i][j]=inf;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(c<g[a][b])
                g[a][b]=g[b][a]=c;
        }
        dijk();
        cout<<dis[n]<<'\n';
    }
    return 0;
}

 

<2>dijkstra+堆优化(邻接矩阵存图)

#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e4+10;
int n,m;

struct qnode
{
    int v;
    int c;
    qnode(int _v=0,int _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const
    {
        return c>r.c;
    }
};

struct Edge
{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};

vector<Edge>E[N];
bool vis[N];
int dis[N];

void dijk(int n,int start)
{
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++)
        dis[i]=inf;
    priority_queue<qnode>q;
    while(!q.empty())
        q.pop();
    dis[start]=0;
    q.push(qnode(start,0));
    qnode tmp;
    while(!q.empty())
    {
        tmp=q.top();
        q.pop();
        int u=tmp.v;
        if(vis[u])
            continue;
        vis[u]=true;
        for(int i=0;i<E[u].size();i++)
        {
            int v=E[tmp.v][i].v;
            int cost=E[u][i].cost;
            if(!vis[v]&&dis[v]>dis[u]+cost)
            {
                dis[v]=dis[u]+cost;
                q.push(qnode(v,dis[v]));
            }
        }
    }
}

void addadge(int u,int v,int w)
{
    E[u].push_back(Edge(v,w));
}

void init()
{
    for(int i=0;i<N;i++)
        E[i].clear();
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&n+m)
    {
        init();
        int u,v,w;
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            addadge(u,v,w);///注意无向图加两条边
            addadge(v,u,w);
        }
        dijk(n,1);
        cout<<dis[n]<<'\n';
    }
    return 0;
}

<3>dijkstra+堆优化(链式前向星存图)

大佬的链式前向星详解

#include <bits/stdc++.h>    ///dijk+堆优化(链式前向星)
using namespace std;
const int N = 1e4 + 7;
const int inf = 0x3f3f3f3f;

int head[N];
bool vis[N];
int dis[N];
int n, m, tot;

struct Node
{
    int u, v, l, next;     ///起点 终点 长度 与该边同起点的上一条边的储存位置
}edge[N];

struct A
{
    int pos, cost;
    bool operator < (const A &a)const
    {
        return cost > a.cost;
    }
};

void addedge(int x, int y, int z)
{
    edge[tot].u = x;
    edge[tot].v = y;
    edge[tot].l = z;
    edge[tot].next = head[x];
    head[x] = tot++;
}

int dijk(int src, int des)
{
    memset(dis, inf, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    priority_queue<A>q;
    dis[src] = 0;
    A now;
    now.cost = 0;
    now.pos = src;
    q.push(now);
    while(!q.empty())
    {
        now = q.top();
        q.pop();
        if(vis[now.pos])
            continue;
        vis[now.pos] = 1;
        for(int i = head[now.pos]; ~i; i = edge[i].next)    //遍历以该点为顶点的所有边
        {
            int to = edge[i].v;    //to = 这条边的终点
            if(!vis[to] && dis[to] > edge[i].l + dis[edge[i].u])    //to没有更新过且目前源点到to的距离 > 该边的长度 + 源点到该边起点的距离
            {
                dis[to] = dis[edge[i].u] + edge[i].l;    //更新
                now.cost = dis[to];
                now.pos = to;
                q.push(now);
            }
        }
    }
    return dis[des];
}

int main()
{
    int u, v, w;
    while(scanf("%d%d", &n, &m) != EOF && n + m)
    {
        tot = 0;
        memset(head, -1, sizeof(head));
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            addedge(u, v, w);
            addedge(v, u, w);
        }
        int ans = dijk(1, n);
        cout<<ans<<'\n';
    }
    return 0;
}

<4>dijkstra+堆优化(pair存储)

 

3.Bellman-ford

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int dis[N];
int n,m;

struct Edge
{
    int u,v,w;
}edge[N];

bool Bellman_Ford()
{
    for(int i=1;i<=n;i++)
        dis[i]=inf;
    dis[1]=0;
    for(int k=1;k<=n-1;k++)
    {
        bool flag=0;
        for(int i=1;i<=2*m;i++)
        {
            if(dis[edge[i].v]>dis[edge[i].u]+edge[i].w)
            {
                dis[edge[i].v]=dis[edge[i].u]+edge[i].w;
                flag=1;
            }
        }
        if(!flag)
            return true;
    }
    for(int j=1;j<=2*m;j++)
        if(dis[edge[j].v]>dis[edge[j].u]+edge[j].w)
            return false;///判负环
    return true;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&n+m)
    {
        int cnt=1;
        int a,b,c;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            edge[cnt].u=edge[cnt+1].v=a;
            edge[cnt].v=edge[cnt+1].u=b;
            edge[cnt].w=edge[cnt+1].w=c;
            cnt+=2;
        }
        if(Bellman_Ford())
            cout<<dis[n]<<'\n';
        else
            cout<<-1<<'\n';
    }
    return 0;
}

4.spfa

<1>朴素版(链式前向星)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int dis[N],vis[N],head[N],num[N];
int n,m,tot;

struct Edge
{
    int u,v,w,next;
}edge[N];

void add(int a,int b,int c)
{
    edge[tot].u=a;
    edge[tot].v=b;
    edge[tot].w=c;
    edge[tot].next=head[a];
    head[a]=tot++;
}

bool spfa(int s)
{
    queue<int>q;
    for(int i=1;i<=n;i++)
        dis[i]=inf;
    memset(vis,false,sizeof(vis));
    memset(num,0,sizeof(num));
    q.push(s);
    dis[s]=0;
    vis[s]=1;
    while(!q.empty())
    {
        int pos=q.front();
        q.pop();
        vis[pos]=false;
        num[pos]++;
        for(int i=head[pos];i!=-1;i=edge[i].next)
        {
            if(dis[edge[i].v]>dis[edge[i].u]+edge[i].w)
            {
                dis[edge[i].v]=dis[edge[i].u]+edge[i].w;
                if(!vis[edge[i].v])
                {
                    vis[edge[i].v]=true;
                    q.push(edge[i].v);
                    if(num[edge[i].v]>=n)
                        return false;
                }
            }
        }
    }
    return true;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&n+m)
    {
        int a,b,c;
        tot=0;
        memset(head,-1,sizeof(head));
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        if(!spfa(1))
            cout<<-1<<'\n';
        else
            cout<<dis[n]<<'\n';
    }
    return 0;
}

<2>SLF优化(链式前向星)

#include <bits/stdc++.h>///spfa   SLF优化
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int dis[N],head[N];
bool vis[N];
int n,m,tot;

struct Edge
{
    int u,v,w,next;
}edge[N];

void add(int a,int b,int c)
{
    edge[tot].u=a;
    edge[tot].v=b;
    edge[tot].w=c;
    edge[tot].next=head[a];
    head[a]=tot++;
}

void spfa(int s)
{
    deque<int>q;
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    vis[s]=true;
    dis[s]=0;
    q.push_back(s);
    while(!q.empty())
    {
        int from=q.front();
        q.pop_front();
        vis[from]=false;
        for(int i=head[from];i!=-1;i=edge[i].next)
        {
            int to=edge[i].v;
            if(dis[to]>dis[from]+edge[i].w)
            {
                dis[to]=dis[from]+edge[i].w;
                if(!vis[to])
                {
                    if(!q.empty()&&dis[to]>=dis[q.front()])///注意
                        q.push_back(to);
                    else
                        q.push_front(to);
                    vis[to]=true;
                }
            }
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&n+m)
    {
        int a,b,c;
        tot=0;
        memset(head,-1,sizeof(head));
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        spfa(1);
        cout<<dis[n]<<'\n';
    }
    return 0;
}

<3>SLF+LLL优化(链式前向星)

#include <bits/stdc++.h>///spfa   SLF+LLL优化
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int dis[N],head[N];
bool vis[N];
int n,m,tot;

struct Edge
{
    int u,v,w,next;
}edge[N];

void add(int a,int b,int c)
{
    edge[tot].u=a;
    edge[tot].v=b;
    edge[tot].w=c;
    edge[tot].next=head[a];
    head[a]=tot++;
}

void spfa(int s)
{
    int num=0;
    long long sum=0;
    deque<int>q;
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    vis[s]=true;
    dis[s]=0;
    q.push_back(s);
    num++;
    while(!q.empty())
    {
        int from=q.front();
        q.pop_front();
        num--;
        sum-=dis[from];
        while(num&&dis[from]>sum/num)
        {
            q.push_back(from);
            from=q.front();
            q.pop_front();
        }
        vis[from]=false;
        for(int i=head[from];i!=-1;i=edge[i].next)
        {
            int to=edge[i].v;
            if(dis[to]>dis[from]+edge[i].w)
            {
                dis[to]=dis[from]+edge[i].w;
                if(!vis[to])
                {
                    if(!q.empty()&&dis[to]<dis[q.front()])
                        q.push_front(to);
                    else
                        q.push_back(to);
                    vis[to]=true;
                    num++;
                    sum+=dis[to];
                }
            }
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&n+m)
    {
        int a,b,c;
        tot=0;
        memset(head,-1,sizeof(head));
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        spfa(1);
        cout<<dis[n]<<'\n';
    }
    return 0;
}

 

全部评论

相关推荐

比亚迪汽车新技术研究院 硬件工程师 总包21左右 硕士
点赞 评论 收藏
分享
牛客5655:其他公司的面试(事)吗
点赞 评论 收藏
分享
Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务