zoukankan      html  css  js  c++  java
  • 最短路 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
  • 相关阅读:
    javaweb开发之解决全站乱码
    redis加入开机启动服务
    linux下安装memcache
    关于本地连接虚拟机(centos)里的mongodb失败问题
    oracle存储过程中返回一个程序集
    面向对象进阶(二)----------类的内置方法
    面向对象进阶(一)
    面向对象的三大特性之----------封装
    面向对象的三大特性之----------多态
    面向对象的三大特性之----------继承
  • 原文地址:https://www.cnblogs.com/stranger-/p/7816299.html
Copyright © 2011-2022 走看看