hdu1874(最短路径问题SPFA)

题意:求最短路径
主要想是学习下SPFA,所以用这个算法来写的
学习链接:http://www.cnblogs.com/devtang/archive/2011/08/25/spfa.html
http://blog.sina.com.cn/s/blog_a46817ff01015g9h.html
SPFA(Shortest Path Faster Algorithm)算法
1、是求单源最短路径的一种算法;2判断图中有无负圈
SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。
它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负圈(如果存在负边不可以用dirkstra算法做原因如下:Dijkstra不断维护最小,每次走使当前权值最小的能边,那么一旦有负的权值每次从这里通过总的权值和就会越来越小,那么这条边会一直是最小边,
Dijkstra算法会使你陷入死循环,不断在这条负权值的边两端的点来回
,但是如果存在负圈,那么最短路不存在,可用SPFA判断有无负圈存在)。若一个点入队次数超过n,则有负权环。
算法大致流程是用一个队列来进行维护
注意点:在实际的应用中SPFA的算法时间效率不是很稳定,为了避免最坏情况的出现,通常使用效率更加稳定的Dijkstra算法。
算法实现:
Dist[i]记录源点到i点的距离
1、 建立一个队列,将源点入队列,初始化源点的dist为0,其他点为oo
2、 每次取队首元素,对其相邻点松弛,松弛成功的入队列

3、 队列为空时算法结束

模板题

代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>

#define N 205
#define inf 0x7ffffff
#define eps 1e-9
#define pi acos(-1.0)
#define P system("pause")
using namespace std;
int n,m;
int mp[N][N],dist[N],vis[N];
queue<int> q;
void SPFA(int s)
{
    memset(vis,0,sizeof(vis));
    while(!q.empty()) q.pop();
    int i;
    for(i = 0; i < n; i++)//注意这里和dijkstra算法不一样
        dist[i] = inf;
    dist[s] = 0;
    q.push(s);
    vis[s] = 1;
    while(!q.empty())
    {
        int temp = q.front();
        //cout<<temp<<endl;
        q.pop();
        for(i = 0; i < n; i++)
            if(dist[i] > mp[temp][i]+dist[temp])
            {
               dist[i] = dist[temp] + mp[temp][i];
                if(!vis[i])
                {
                    //cout<<i<<endl;
                    q.push(i);
                    vis[i] =1;
                }
            }
        vis[temp] = 0;
    }
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
    while(scanf("%d%d",&n,&m) != EOF)
    {
        int i,j;
        for(i = 0; i < n; i++)
            for(j = 0; j < n; j++)
                mp[i][j] = mp[j][i] = inf;
        for(i = 0 ; i < m; i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if(mp[x][y] > z)
                mp[x][y] = mp[y][x] = z;
        }
        int start ,end;
        scanf("%d%d",&start,&end);
        SPFA(start);
        if(dist[end] == inf) printf("%d\n",-1);
        else printf("%d\n", dist[end]);


    }


    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值