SPFA最短路径

SPFA最短路径



并没有详细讲解,只是保存模板。

题目

要求

给定一个图,一个源点,求这个点到每个其他点的最短路径。
输入和输出
输入
第一行:n,m(点数和路径数)
接下来m行:x,y,len(两个相连的点,路径长度)无向
最后一行:数字st,表示源点

输出
由st向各个其他点走的最短路径(按照点编号顺序,间隔一个空格输出)
样例
样例输入

5 7
1 2 2
1 5 10
2 3 3
2 5 7
3 4 4
4 5 5
5 3 6
1

image

样例输出

0 2 5 9 9

提示
一个点和自己的间距是0

代码

  1. 邻接表版
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#define maxn (100000+10) 
using namespace std;
struct node{
    int next,to,w;
} e[maxn];
int n,m,st/*输入的源点*/;
int cnt=1,head[maxn],dis[maxn],vis[maxn];

queue <int> q;

void add(int x,int y,int len){
    e[cnt].to=y;
    e[cnt].w=len;
    e[cnt].next=head[x];
    head[x]=cnt;
    cnt++;
}
void spfa(int x)/*源点*/{
    q.push(x);
    dis[x]=0;
    while(!q.empty()){
        int cur=q.front();
        q.pop();
        for(int i=head[cur];~i;i=e[i].next){
            if(dis[e[i].to]>e[i].w+dis[cur]){
                dis[e[i].to]=e[i].w+dis[cur];
                if(!vis[e[i].to]){
                    vis[e[i].to]=1;
                    q.push(e[i].to); 
                }
            }
        }
    }   

} 
int main(){
    ios::sync_with_stdio(false);

    memset(head,-1,sizeof(head));
    memset(dis,0x3f3f3f3f,sizeof(dis));
    memset(vis,0,sizeof(vis));

    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y,len;
        cin>>x>>y>>len;
        add(x,y,len);
        add(y,x,len);
    }
    cin>>st;
    spfa(st);
    for(int i=1;i<=n;i++)
        cout<<dis[i]<<" ";
    return 0;
}

2 . Vector版

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<vector>
#define maxn (100000+10) 
using namespace std;
struct E{
    int p;
    int dis;
};
int n,m,st/*输入的源点*/;
int head[maxn],dis[maxn],vis[maxn];

vector<E> edge[maxn];

void add(int x,int y,int len){
    E temp;
    temp.dis=len;temp.p=y;
    edge[x].push_back(temp);
}

queue <int> q;
void spfa(int x)/*源点*/{
    q.push(x);
    dis[x]=0;
    while(!q.empty()){
        int cur=q.front();
        q.pop();
        int len=edge[cur].size();
        for(int i=0;i<len;i++){
            if(dis[edge[cur][i].p]>edge[cur][i].dis+dis[cur]){
                dis[edge[cur][i].p]=edge[cur][i].dis+dis[cur];
                if(!vis[edge[cur][i].p]){
                    vis[edge[cur][i].p]=1;
                    q.push(edge[cur][i].p); 
                }
            }
        }
    }   
} 
int main(){
    ios::sync_with_stdio(false);
    memset(head,-1,sizeof(head));
    memset(dis,0x3f3f3f3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y,len;
        cin>>x>>y>>len;
        add(x,y,len);
        add(y,x,len);
    }
    cin>>st;
    spfa(st);
    for(int i=1;i<=n;i++)
        cout<<dis[i]<<" ";
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值