spfa算法判断负环

8 篇文章 0 订阅

852. spfa判断负环

在这里插入图片描述

// spfa判断负环

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int N = 100010;

int n, m;
int h[N], w[N], e[N], ne[N], idx; //邻接表
int dist[N], cnt[N];              //该点距离起点的距离, 到达该点经过的边数(n条边有n+1个点)
bool st[N];                       //是否在队列中

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

int spfa()
{
    //不需要初始化,w[i]为负,dist[j] > dist[t] + w[i]一定成立
    //初始化
    // memset(dist,0x3f,sizeof dist);
    // dist[1] = 0;

    queue<int> q; //创建队列
    //把所有的点放进来,看看所有点为起点是否存在负环
    for (int i = 1; i <= n; i++) //添加一个权值为0的虚拟点,不会改变原有的数据关系
    {
        q.push(i);    //把第一个点存入队列
        st[i] = true; //标记为已在队列
    }

    while (q.size())
    {
        int t = q.front();
        q.pop();

        st[t] = false; //已不在队列

        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];                 //点的序号
            if (dist[j] > dist[t] + w[i]) //权重的下标是idx,h[]存的正是这个,
            {
                dist[j] = dist[t] + w[i];
                cnt[j] = cnt[t] + 1;//又经过了一条边

                if (cnt[j] >= n)
                    return true; //n个边就存在n+1个点 由于抽屉原则一定有两个点是重复
                if (!st[j])
                {
                    q.push(j);    //存入队列
                    st[j] = true; //标记为已在队列
                }
            }
        }

    } //更无可更,便是结果
    return false;
}

int main()
{
    //邻接表初始化
    memset(h, -1, sizeof h);
    scanf("%d%d", &n, &m); //n个点,m条边

    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
    }

    if (spfa())
        puts("Yes");
    else
        puts("No");

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值