(原创)(草稿)升级版dijkstra算法,可以处理负边权

后期再补齐原理,先说一下局限性,就是图中不得有自边和负边权

//Dijkstra升级版 可以处理负边权
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <unordered_map>
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3f;

const long long N = 1e5 + 10, M = 2e6 + 10;

long long n, m, s;

struct Node
{
    long long to;
    long long weight;
};
Node NNN;
vector<Node> g[N];

bool vis[N];
long long d[N];
long long d1[N];
// 点u, d[u]

struct VNode
{
    long long p;
    long long d;
    bool operator<(const VNode &b) const
    {
        return d > b.d;
    }
};
VNode NNNN;
void dijkstra(long long s)
{
    priority_queue<VNode> q;
    for (long long i = 1; i <= n; i++)
    {
        d[i] = INF;
    }
    d[s] = 0;
    NNNN.p = s;
    NNNN.d = 0;
    q.push(NNNN);
    while (!q.empty())
    {
        long long u = q.top().p; // 找到堆顶元素
        q.pop();
        if (vis[u]) // 如果已经找到了, 就不要再操作了
        {
            continue;
        }
        // 如果已经在S集合中了, 就不要操作了, 只有在T集合中的点, 我们才
        // 拿进去, 然后松弛
        vis[u] = 1;
        for (auto e : g[u])
        {
            long long v = e.to;
            long long w = e.weight;
            if (vis[v] == 0 && d[v] > d[u] + w)
            {
                //cout << v << endl;
                d1[v] = 1 + d1[u]; //
                d[v] = d[u] + w;
                NNNN.p = v;
                NNNN.d = d[v];
                q.push(NNNN);
            }
        }
    }
}
long long tigao = INF;
signed main()
{
    cin >> n >> m >> s;
    for (long long i = 1; i <= m; i++)
    {
        long long u, v, w;
        cin >> u >> v >> w;
        NNN.to = v;
        NNN.weight = w;
        g[u].push_back(NNN);
        tigao = w < 0 ? min(tigao, w) : tigao;
    }
    if (tigao != INF)
    {
        tigao = 1 - tigao;
        for (long long i = 1; i <= n; i++)
        {
            for (auto &j : g[i])
            {
                j.weight += tigao;
                // cout<<j.weight<<endl;
            }
        }
    }
    else
        tigao = 0;
    dijkstra(s);
    for (long long i = 1; i <= n; i++)
    {
        if (d[i] == INF){cout << "NO"<< " ";continue;}
        cout << d[i] - d1[i] * tigao << endl;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值