POJ 1201 Intervals

题目链接:POJ 1201 Intervals

题目大意:

题解:
该题是一个差分约束系统。
\(f[i]\)表示在\([0,i]\)区间内取了多少个数。
由输入可以得到多个不等式\(f[b] - f[a - 1] \geq c\),则在建图过程中点\(a-1\)有一条权值为\(c\)的有向边到点\(b\)
同时题目本身存在隐藏限制条件\(1\geq f[i] - f[i-1] \geq 0(0 \leq i \leq maxn)\),即\(\left\{\begin{matrix}f[i] - f[i-1] \geq 0 \\f[i-1] - f[i] \geq -1\end{matrix}\right.\),则在建图过程中每个点\(i-1\)有一条权值为\(0\)的有向边到点\(i\),点\(i\)有一条权值为\(-1\)的有向边到点\(i-1\)
由于区间左端最小可以为\(0\),所以需要将数组下标加\(1\),防止出现下标为\(-1\)的情况。
建图完成之后跑最长路即可。

#include <iostream>
#include <queue>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

struct Edge {
    int v, w, next;
} edge[5000010];
int n, a, b, c, cnt, head[50005], dis[50005], maxb;
bool vis[50005];

void addEdge(int u, int v, int w) {
    edge[++cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

void spfa(int s) {
    queue<int> q;
    for (int i = 0; i <= maxb + 1; ++i) {
        dis[i] = -1;
    }
    dis[s] = 0;
    vis[s] = true;
    q.push(s);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u]; i; i = edge[i].next) {
            int v = edge[i].v;
            if (dis[v] < dis[u] + edge[i].w) {
                dis[v] = dis[u] + edge[i].w;
                if (!vis[v]) {
                    q.push(v);
                    vis[v] = true;
                }
            }
        }
    }
}

int main() {
    io_speed_up;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a >> b >> c;
        addEdge(a, b + 1, c);
        maxb = maxb >= b ? maxb : b;
    }
    for (int i = 1; i <= maxb + 1; ++i) {
        addEdge(i - 1, i, 0);
        addEdge(i, i - 1, -1);
    }
    spfa(0);
    cout << dis[maxb + 1] << endl;
    return 0;
}
posted @ 2022-01-30 20:09  ZZHHOOUU  阅读(72)  评论(0编辑  收藏  举报