1. 程式人生 > >[Luogu 3275] SCOI2011 糖果

[Luogu 3275] SCOI2011 糖果

[Luogu 3275] SCOI2011 糖果

<題目連結>


第一道差分約束。感謝 AZe。

我的理解是根據一些不等關係建一個圖,在圖上邊跑一個最長路(有時候是最短路)。

因為可能存在負環,所以必須用 SPFA!

好神奇啊,圖論好強強啊。

然而 Capella 慘慘,用上了 0 號節點卻從 1 開始初始化鄰接表,導致 for 出不去了,就因為這個調了一個晚上。

指標選手初始化很重要啊。

加油qwq

#include <algorithm>
#include <cstdio>
#include <queue>

#define nullptr NULL

const int MAXN = 100010; 

int n, k; 
long long ans; 

struct Graph
{
    struct Edge
    {
        int to; 
        long long w; 
        Edge *next; 
        Edge(int to, long long w, Edge* next): to(to), w(w), next(next) {}
        ~Edge(void)
        {
            if(next != nullptr)
                delete next; 
        }
    }*head[MAXN]; 
    Graph(int n)
    {
        std :: fill(head, head + n + 1, (Edge*)nullptr); 
    }
    ~Graph(void)
    {
        for(int i = 1; i <= n; ++i)
            delete head[i]; 
    }
    void AddEdge(int u, int v, long long w)
    {
        head[u] = new Edge(v, w, head[u]); 
    }
    void Build(int x, int a, int b)
    {
        if(x % 2 == 0 && a == b)
        {
            puts("-1"); 
            exit(0); 
        }
        switch(x)
        {
            case 1: 
                AddEdge(a, b, 0LL); 
                AddEdge(b, a, 0LL); 
                break; 
            case 2: 
                AddEdge(a, b, 1LL); 
                break; 
            case 3: 
                AddEdge(b, a, 0LL); 
                break; 
            case 4: 
                AddEdge(b, a, 1LL); 
                break; 
            case 5: 
                AddEdge(a, b, 0LL); 
                break; 
        }
    }
}*G; 

namespace DiffConst
{
    bool exist[MAXN]; 
    int cnt[MAXN]; 
    long long dist[MAXN]; 
    bool SPFA(int S)
    {
        std :: queue<int> Q; 
        Q.push(S); 
        exist[S] = true; 
        while(!Q.empty())
        {
            int u = Q.front(), v; 
            Q.pop(); 
            exist[u] = false; 
            for(Graph :: Edge *i = G -> head[u]; i != nullptr; i = i -> next)
                if(dist[v = i -> to] < dist[u] + i -> w)
                {
                    if(!exist[v])
                    {
                        if(++cnt[v] == n)
                            return false; 
                        Q.push(v); 
                        exist[v] = 1; 
                    }
                    dist[v] = dist[u] + i -> w; 
                }
        }
        return true; 
    }
}

int main(void)
{
    scanf("%d %d", &n, &k); 
    G = new Graph(n); 
    for(int i = 1, x, a, b; i <= k; ++i)
    {
        scanf("%d %d %d", &x, &a, &b); 
        G -> Build(x, a, b); 
    }
    for(int i = n; i >= 1; --i)
        G -> AddEdge(0, i, 1LL); 
    if(DiffConst :: SPFA(0))
    {
        for(int i = 1; i <= n; ++i)
            ans += DiffConst :: dist[i]; 
        printf("%lld\n", ans); 
    }
    else
        puts("-1"); 
    return 0; 
}

謝謝閱讀。