ACM_SPFA算法

SPFA算法:首先源点到源点的距离为0,然后用源点对其他点进行松弛操作(更新操作),若松弛成功,表明源点到其的路径变小了,那么该点有可能能作为中间点松弛其他点,所以得将其入队列(如果它不在队列里面的话)某个点得到了松弛,如果它在队列里面,那么它能松弛的点会在接下的过程中得到松弛,如果它在这之前已经松弛了其他点,那么由于它受到了松弛,则那些它可以松弛的点将会进一步被松弛,所以它得重新入队列;如果没有负权值的边,那么松弛操作不会一直下去,当队列里的元素为空时,算法结束!

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
#define len 100
#define INF 9999999
int n,m,s,d,dis[len],vis[len],road[len][len],cot[len];
//n个点,m条边,s源点,d终点;dis[i]->s到i的最短距离,
//vis[i]判断i是否在队列中,road数组存图,cot[i]表示i进
//队列的次数,也就是i更新dis数组的次数
bool spfa()
{
    int i,t;;
    for (i = 1; i <= n; ++i)
        dis[i] = INF;//初始时,源点到其他点的距离为无穷大
    memset(vis,0,sizeof(vis));
    memset(cot,0,sizeof(cot));
    queue<int>q;
    q.push(s);
    dis[s] = 0;
    vis[s] = 1;
    while (!q.empty())
    {
        t = q.front();
        q.pop();
        vis[t] = 0;
        ++cot[t];
        if (cot[t] > n)
            return false;
        for (i = 1; i <= n; ++i)
        {
            if (dis[i] > dis[t] + road[t][i])
/*
假设1,2之间存在负权值的边,如果1(或2)为源点,那么当i=2时,dis[2]更新(无穷大->负值),
2入队列;当2出队列,i=1时,dis[1]被更新(0->负值),1入队列,2被更新......那么对列将不会
为空
*/
            {
                dis[i] = dis[t] + road[t][i];
                if (!vis[i])
                {
                    q.push(i);
                    vis[i] = 1;
                }
            }
        }
    }
    return true;
}
int main()
{
    int i,j,u,v,w;
    while (cin>>n>>m)
    {
        for (i = 1; i <= n; ++i)
        {
            for (j = 1; j <= n; ++j)
                road[i][j] = i == j ? 0 : INF;
        }
        for (i = 1; i <= m; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            road[u][v] = road[v][u] = w;
        }
        scanf("%d%d",&s,&d);
        if (spfa())
        {
            cout<<dis[d]<<endl;
        }
        else
            cout<<"sorry"<<endl;
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值