[SCOI2011]糖果

Link
一道非常好的差分约束系统的板子题,正好可以借此回顾一下差分约束的有关内容。
假设我们现在有N个方程,
$X_1 - X_2 \leq 0$
$X_1 - X_5 \leq 1$
$X_2 - X_5 \leq 1$
$X_3 - X_1 \leq 5$
$X_4 - X_1 \leq 4$
$X_4 - X_3 \leq - 1$
$X_5 - X_3 \leq - 3$
$X_5 - X_4 \leq - 3$
这样第一个方程组,我们当然可以解不等式组,但是如果我们要求电脑计算的话就需要一些方法,比如说最短路
对于这道题来说,我们对于每一种情况。

  1. Add(X, Y, 0), Add(Y, X, 0) ;
  2. Add(X, Y, 1) ;
  3. Add(Y, X, 0) ;
  4. Add(Y, X, 1) ;
  5. Add(X, Y, 0) ;
    并且还要特判一下当$Type = 2$ 或 $4$ 的时候,如果$X == Y$那么久一定是没有解的。
    然后直接跑SPFA就是了。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>

    using namespace std ;

    typedef long long LL ;
    const LL MAXN = 1000100 ;
    const LL MAXM = 1000100 ;
    const LL Inf = 1000000000 ;

    inline LL Read() {
    LL X = 0, F = 1 ; char ch = getchar() ;
    while (ch > '9' || ch < '0') F = (ch == '-' ? - 1 : 1), ch = getchar() ;
    while (ch >= '0' && ch <= '9') X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ;
    return X * F ;
    }

    LL N, M, H[MAXN], Tot, D[MAXN], INQ[MAXN], F, Num[MAXN] ;
    struct Node {
    LL F, T, L, Next ;
    } E[MAXM << 1] ;

    inline void Add(LL F, LL T, LL L) {
    E[++ Tot].F = F ; E[Tot].T = T ; E[Tot].L = L ;
    E[Tot].Next = H[F] ; H[F] = Tot ;
    }

    inline long long Spfa(LL S) {
    queue <LL> Q ;
    for (register LL i = 1 ; i <= N ; i ++)
    D[i] = 0, INQ[i] = 0, Num[i] = 0 ;
    Q.push(S) ; D[S] = 0 , INQ[S] = 1 ;
    while (! Q.empty()) {
    LL Now = Q.front() ; Q.pop() ; INQ[Now] = 0 ;
    if (Num[Now] == N - 1) return - 1 ; Num[Now] ++ ;
    for (register LL i = H[Now] ; i ; i = E[i].Next)
    if (D[E[i].T] < D[Now] + E[i].L) {
    D[E[i].T] = D[Now] + E[i].L ;
    if (! INQ[E[i].T])
    Q.push(E[i].T), INQ[E[i].T] = 1 ;
    }
    } long long Ans = 0 ;
    for (LL i = 1 ; i <= N ; i ++) Ans += D[i] ;
    return Ans ;
    }

    int main() {
    //freopen("testdata.in", "r", stdin) ;
    N = Read() ; M = Read() ;
    for (register LL i = 1 ; i <= M ; i ++) {
    LL Type = Read(), X = Read(), Y = Read() ;

    if (Type == 1) Add(X, Y, 0), Add(Y, X, 0) ;
    if (Type == 2) Add(X, Y, 1) ;
    if (Type == 3) Add(Y, X, 0) ;
    if (Type == 4) Add(Y, X, 1) ;
    if (Type == 5) Add(X, Y, 0) ;

    if (Type == 2 || Type == 4)
    if (X == Y)
    return puts("-1"), 0 ;
    }
    for (register LL i = N ; i >= 1 ; i --)
    Add(0, i, 1) ;
    printf("%lld\n", Spfa(0)) ;
    }

本文标题:[SCOI2011]糖果

文章作者:Sue Shallow

发布时间:2019年05月26日 - 11:06:47

最后更新:2019年11月11日 - 19:53:56

原始链接:http://Yeasion.github.io/2019/05/26/SCOI2011-糖果/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。