最短路-Dijstra算法和spfa算法模板

一:Dijstra模板

给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值。

请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1。

输入格式

第一行包含整数n和m。

接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

输出格式

输出一个整数,表示1号点到n号点的最短距离。

如果路径不存在,则输出-1。

数据范围

1≤n≤5001≤n≤500,
1≤m≤1051≤m≤105,
图中涉及边长均不超过10000。

输入样例:

3 3
1 2 2
2 3 1
1 3 4

输出样例:

3

 思路:

               

                                    

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N=510;
int g[N][N];

bool st[N]; //用于在更新最短距离时 判断当前的点的最短距离是否确定 是否需要更新
int dist[N];//用于存储每个点到起点的最短距离
int n,m;

int Dijstra()
{
    memset(dist,0x3f,sizeof dist);
    
    dist[1]=0;

    for(int i=0;i<n;i++)
    {
        int t=-1;
        //每次迭代的过程中我们都先找到当前未确定的最短距离的点中距离最短的点
        for(int j=1;j<=n;j++)
            if(!st[j] && (t==-1 || dist[t]>dist[j]))
             t=j;
             
        //更新最短距离的点到其他点的距离
        for(int j=1;j<=n;j++)
            dist[j]=min(dist[j],dist[t]+g[t][j]);
            
        st[t]=true;
    }
    
    if(dist[n]==0x3f3f3f3f) return -1;
    
    return dist[n];
}

int main()
{
    
    cin>>n>>m;
    memset(g,0x3f,sizeof g);
    memset(st,0,sizeof st);
    
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=min(g[a][b],c);
    }
    
    int t=Dijstra();
    
    cout<<t<<endl;
    return 0;
}

SPFA算法模板:

例题:

给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数

请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出impossible。

数据保证不存在负权回路。

输入格式

第一行包含整数n和m。

接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

输出格式

输出一个整数,表示1号点到n号点的最短距离。

如果路径不存在,则输出”impossible”。

数据范围

1≤n,m≤1051≤n,m≤105,
图中涉及边长绝对值均不超过10000。

输入样例:

3 3
1 2 5
2 3 -3
1 3 4

输出样例:

2

 思路:

        SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA一般情况复杂度是O(m)O(m) 最坏情况下复杂度和朴素 Bellman-Ford 相同,为O(nm)O(nm)。

 2、spfa算法步骤
 queue <– 1
while queue 不为空
 (1) t <– 队头
 queue.pop()
 (2)用 t 更新所有出边 t –> b,权值为w
 queue <– b (若该点被更新过,则拿该点更新其他点)

时间复杂度 一般:O(m) 最坏:O(nm)
n为点数,m为边数

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;
const int N=100010;

int h[N],e[N],ne[N],w[N],idx;

bool st[N];
int dist[N];
int n,m;

void add(int a,int b,int c)
{
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}
int spfa()
{
    
    memset(dist,0x3f,sizeof dist);
    //初始化,将1号点放入队列
    dist[1]=0;
    queue<int> q;
    q.push(1);
    st[1]=true;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>dist[t]+w[i])
            {
                dist[j]=dist[t]+w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    if(dist[n]==0x3f3f3f3f) return -1;
    return dist[n];
}


int main()
{
    scanf("%d%d",&n,&m);
    //初始化邻接表
    memset(h,-1,sizeof h);
    
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
        
    }
    
    int t=spfa();
    if(t==-1) puts("impossible");
    else 
    printf("%d",t);
}
发布了22 篇原创文章 · 获赞 7 · 访问量 408

猜你喜欢

转载自blog.csdn.net/qq_40905284/article/details/104422432
今日推荐