洛谷-P1250 種樹

carboxylBase發表於2024-08-13

Abstract

傳送門

Idea

顯然是一個差分約束系統。不妨用 dist[i] 表示前 i 個位置種的樹的數目,那麼,容易得出下列方程:

  1. dist[i] >= dist[i-1]
  2. dist[i] - dist[i-1] <= 1 (每個位置至多能種一顆樹)

題目要求 b 到 e 之間至少種 t 棵樹,其數學形式就是:

  1. dist[b] - dist[e-1] >= t

依據上面三種方程,我們構建了一個完整的差分約束系統,接下來跑最短路求出 dist 陣列的一個可能取值就行了。然後,考慮到邊界條件 dist[0] = 0,所以答案是 dist[n] - dist[0] 。

Code

#include <bits/stdc++.h>
using namespace std;
int n, h;
namespace graph
{
    const int maxn = 100000;
    int head[maxn];
    int cnt;
    struct Edge
    {
        int next, to, value;
    } edge[maxn];
    void add(int u, int v, int c)
    {
        edge[++cnt].next = head[u];
        edge[cnt].to = v;
        edge[cnt].value = c;
        head[u] = cnt;
        return;
    }
};

bool SPFA(int start, int dist[])
{
    queue<int> q;
    bool inQueue[graph::maxn] = {false};
    int count[graph::maxn] = {0};
    for (int i = 1; i < n + 1; i++)
    {
        dist[i] = 0x3f3f3f3f;
    }
    dist[start] = 0;
    q.push(start);
    inQueue[start] = true;
    count[start] = 1;

    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        inQueue[u] = false;

        for (int i = graph::head[u]; i; i = graph::edge[i].next)
        {
            int v = graph::edge[i].to;
            int w = graph::edge[i].value;
            if (dist[u] + w < dist[v])
            {
                dist[v] = dist[u] + w;
                if (!inQueue[v])
                {
                    q.push(v);
                    inQueue[v] = true;
                    count[v]++;
                }
                if (count[v] > n + 1)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

void solve()
{
    cin >> n >> h;
    for (int i = 0; i < h; i++)
    {

        int e, b, t;
        cin >> b >> e >> t;
        graph::add(e, b - 1, -t);
    }

    for (int i = 0; i < n; i++)
    {
        graph::add(i, i + 1, 1);
        graph::add(i + 1, i, 0);
    }
    for (int i = 0; i < n + 1; i++)
    {
        graph::add(n + 1, i, 0);
    }

    int dist[graph::maxn];
    SPFA(n + 1, dist);
    cout << dist[n] - dist[0];
    return;
}

signed main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

相關文章