P5960 【模板】差分约束算法

题目描述

给出一组包含 $m$ 个不等式,有 $n$ 个未知数的形如:

 的不等式组,求任意一组满足这个不等式组的解。

输入格式

第一行为两个正整数 $n,m$,代表未知数的数量和不等式的数量。

接下来 $m$ 行,每行包含三个整数 $c,c',y$,代表一个不等式 $x_c-x_{c'} \leqslant y$。

输出格式

一行,$n$ 个数,表示 $x_1​,x_2​⋯x_n$​ 的一组可行解,如果有多组解,请输出任意一组,无解请输出$NO$。

样例数据

输入

3 3
1 2 3
2 3 -2
1 3 1

输出

5 3 5

分析

将$0$与每个点连一条长度为$0$的边,以$0$为起点求单源最短路,如果判断有负环那么该组不等式无解,否则$x_i=Dis_i$就是一组解

代码

#include <bits/stdc++.h>

#define Enter puts("")
#define Space putchar(' ')

using namespace std;

typedef long long ll;
typedef double Db;

inline ll Read()
{
    ll Ans = 0;
    char Ch = getchar() , Las = ' ';
    while(!isdigit(Ch))
    {
        Las = Ch;
        Ch = getchar();
    }
    while(isdigit(Ch))
    {
        Ans = (Ans << 3) + (Ans << 1) + Ch - '0';
        Ch = getchar();
    }
    if(Las == '-')
        Ans = -Ans;
    return Ans;
}

inline void Write(ll x)
{
    if(x < 0)
    {
        x = -x;
        putchar('-');
    }
    if(x >= 10)
        Write(x / 10);
    putchar(x % 10 + '0');
}
const int N = 1000000;

int n , m;
int Count[N] , Dis[N] , Head[N];
int Total = 0;
bool Visit[N] , t;

queue <int> Q;

struct Edge
{
    int Dis;
    int Next;
    int To;
}E[2 * N];

inline void Add_Edge(int u , int v , int w)
{
    E[++Total].Dis = w;
    E[Total].To = v;
    E[Total].Next = Head[u];
    Head[u] = Total;
}

inline bool SPFA()
{
    for(int i = 0; i <= n; i++)
    {
        Visit[i] = 0;
        Dis[i] = 1e6;
    }
    Visit[0] = 1 , t = 0 , Dis[0] = 0;
    Q.push(0);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        Visit[u] = 0;
        for(int i = Head[u]; i;i = E[i].Next)
        {
            int v = E[i].To , w = E[i].Dis;
            if(Dis[v] > Dis[u] + w)
            {
                Dis[v] = Dis[u] + w;
                if(Count[v] >= n)
                    return false;
                if(!Visit[v])
                    Visit[v] = 1 , Count[v]++ , Q.push(v);
            }
        }
    }
    return true;
}

int main()
{
    n = Read() , m = Read();
    for(int i = 1; i <= m; i++)
    {
        int u = Read() , v = Read() , w = Read();
        Add_Edge(v , u , w);
    }
    for(int i = 1; i <= n; i++)
        Add_Edge(0 , i , 0);
    if(SPFA() == false)
        puts("NO");
    else
        for(int i = 1; i <= n; i++)
            Write(Dis[i]) , Space;
    return 0;
}

 

posted @ 2021-05-21 16:21  Tenderfoot  阅读(116)  评论(0编辑  收藏  举报