蓝桥杯算法练习最短路(spfa)

spfa算法详解

http://www.360doc.com/content/13/1208/22/14357424_335569176.shtml

代码详解

#include<iostream>
#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;
#define inf 999999999
typedef struct minx
{
    int a,d;
}node;
int dis[20005],n;
vector<node>map[20005];
void init()
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=inf;
    }
}
void spfa()
{
    queue<int>q;
    int book[20005]={0},t;
    q.push(1);
    book[1]=1;
    dis[1]=0;
    while(!q.empty())
    {
        t=q.front();
        q.pop();
        book[t]=0;
        int len=map[t].size(),a;
        for(int i=0;i<len;i++)
        {
            a=map[t][i].a;
            if(dis[a]>map[t][i].d+dis[t])
            {
                dis[a]=map[t][i].d+dis[t];
                if(!book[a])
                {
                    book[a]=1;
                    q.push(a);
                }
            }
        }
    }
}
int main()
{
    int m,a,b,l;
    node Now;
    while(~scanf("%d %d",&n,&m))
    {
        init();
        while(m--)
        {
            scanf("%d %d %d",&a,&b,&l);
            Now.a=b,Now.d=l;
            map[a].push_back(Now);
        }
        spfa();
        for(int i=2;i<=n;i++)
            printf("%d\n",dis[i]);
    }
    return 0;
}
dijkstra算法,会超时,且只能用于边为正的

   memset(book,0,sizeof book);
        for(i=2;i<=n;i++)
            d[i]=inf;
        d[1]=0;
        for(i=1;i<=n;i++)
        {
            int x,m=inf;
            for(j=1;j<=n;j++)
            {
                if(!book[j]&&d[j]<=m)
                    m=d[x=j];
            }
            book[x]=1;
            for(j=0;j<=n;j++)
            {
                d[j]=min(d[j],d[x]+e[x][j]);
            }
        }
Floyd算法

for(int k=0;k<n;k++)
    for(int i=0;i<n;k++)
        for(int j=0;j<n;j++)
            d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
Bellman-Ford算法
http://blog.csdn.net/guixunlong/article/details/8474263

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 9999999
typedef struct
{
    int u,v,cost;
}Edge;
Edge edge[200001];
int pre[200001];
int dis[200001];
int m,n;
int original;
bool bellman_ford()
{
    for(int i=2;i<=n;i++)
        dis[i]=MAX;
    for(int i=1;i<=n-1;i++)
        for(int j=1;j<=m;j++)
            if(dis[edge[j].v]>dis[edge[j].u]+edge[j].cost)
            {
                dis[edge[j].v]=dis[edge[j].u]+edge[j].cost;
                pre[edge[j].v]=edge[j].u;
            }
    bool flag=true;
    //bellman-ford的一个优势是可以用来判断是否存在负环的在不存在负环的情况下,进行了n-1次所有边的更新
    //操作后每个结点的最短路径都确定了,在用所有边去更新一次不会改变结果的。如果存在负环,最后再更新一次会改变结果
    //原因是之前是假定了起点的最短路距离是确定的并且是最短的
    //而有负环的情况下这个假设不再成立
    //
    for(int i=1;i<=m;i++)
    {
        if(dis[edge[i].v]>dis[edge[i].u]+edge[i].cost)
        {
            flag=false;
            break;
        }
    }
    return flag;
}
int main()
{
    while(cin>>n>>m)
    {
        pre[1]=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].cost);
        }
        if(bellman_ford())
        {
            for(int i=2;i<=n;i++)
                cout<<dis[i]<<endl;
        }
    }
    return 0;
}

三个算法的分析
http://blog.csdn.net/mmy1996/article/details/52225893


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值