最短路 spfa 算法 && 链式前向星存图

推荐博客  https://i.cnblogs.com/EditPosts.aspx?opt=1

      http://blog.csdn.net/mcdonnell_douglas/article/details/54379641

spfa  自行百度 说的很详细

spfa 有很多实现的方法  dfs  队列  栈  都可以 时间复杂度也不稳定 不过一般情况下要比bellman快得多

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <queue>
#include <ctime>
#include <vector>
using namespace std;
const int maxn= 1e3+5;
const int maxm= 1e3+5;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m,s;   //n m s 分别表示 点数-标号从1开始 边数-标号从0开始 起点
struct edge
{
    int to,w;
};
int d[maxn];   //d[i]表示 i 点到源点 s 的最短距离
int p[maxn];    //p[i]记录最短路到达 i 之前的节点
int visit[maxn]; // 标记是否已进队
int cnt[maxn];
vector<edge> v[maxn];
int spfa(int x)
{
    queue<int> q;
    memset(visit,0,sizeof(visit));
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)
        d[i]=inf;
    d[x]=0;
    visit[x]=1;
    q.push(x);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        visit[u]=0;
        for(int i=0;i<v[u].size();i++)
        {
            edge &e=v[u][i];
            if(d[u]<inf&&d[u]+e.w<d[e.to])
            {
                d[e.to]=d[u]+e.w;
                p[e.to]=u;
                if(!visit[e.to])
                {
                    q.push(e.to);
                    visit[e.to]=1;
                    if(++cnt[e.to]>n)
                        return 0;
                }
            }
        }
    }
    return 1;
}
void Print_Path(int x)
{
    while(x!=p[x])          //逆序输出 正序的话用栈处理一下就好了
    {
        printf("%d ",x);
        x=p[x];
    }
    printf("%d
",x);
}
int main()
{
    while(scanf("%d %d %d",&n,&m,&s)!=EOF)
    {
        int x,y,z;
        for(int i=0;i<m;i++)
        {
            scanf("%d %d %d",&x,&y,&z);
            edge e;
            e.to=y;
            e.w=z;
            v[x].push_back(e);
//            e.to=x;           //无向图 反向建边
//            v[y].push_back(e);
        }
        p[s]=s;
        if(spfa(s)==1)
            for(int i=1;i<=n;i++)
            {
                printf("%d %d
",i,d[i]);
                Print_Path(i);
            }
        else
            printf("sorry
");
        return 0;
    }
}

链式前向星存图 

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 #include <iostream>
 6 #include <sstream>
 7 #include <algorithm>
 8 #include <string>
 9 #include <queue>
10 #include <ctime>
11 #include <vector>
12 using namespace std;
13 const int maxn= 1e3+5;
14 const int maxm= 1e3+5;
15 const int inf = 0x3f3f3f3f;
16 typedef long long ll;
17 int n,m;
18 int first[maxn];
19 struct edge
20 {
21     int to,next,w;
22 }e[maxn];
23 void add(int i,int u,int v,int w)
24 {
25     e[i].to=v;
26     e[i].w=w;
27     e[i].next=first[u];
28     first[u]=i;
29 }
30 int main()
31 {
32     scanf("%d %d",&n,&m);
33     {
34         int u,v,w;
35         memset(first,-1,sizeof(first));
36         for(int i=0;i<m;i++)
37         {
38             scanf("%d %d %d",&u,&v,&w);
39             add(i,u,v,w);
40         }
41         for(int i=1;i<=n;i++)
42         {
43              cout<<"from"<<i<<endl;
44              for(int j=first[i];j!=-1;j=e[j].next)  //遍历以j为起点的每条边
45                 cout<<"to"<<e[j].to<<" length="<<e[j].w<<endl;
46         }
47 
48     }
49 }
50 //输入
51 //6 9
52 //1 2 2
53 //1 4 -1
54 //1 3 1
55 //3 4 2
56 //4 2 1
57 //3 6 3
58 //4 6 3
59 //6 5 1
60 //2 5 -1
61 //输出
62 //from1
63 //to3 length=1
64 //to4 length=-1
65 //to2 length=2
66 //from2
67 //to5 length=-1
68 //from3
69 //to6 length=3
70 //to4 length=2
71 //from4
72 //to6 length=3
73 //to2 length=1
74 //from5
75 //from6
76 //to5 length=1
原文地址:https://www.cnblogs.com/stranger-/p/7816299.html