poj 1201 Intervals 差分约束系统

Poj 1201 Intervals

题目链接

​ 差分约束系统。

​ 设\(s[x]\)表示从横坐标为0到横坐标为\(x\)的最少点数,所以求出\(s[maxn]\)就好了。(\(maxn\)为横坐标最大的数)

​ 根据每个区间最少的点数,我们可以得到:\(s[y] - s[x - 1] >= c\)

​ 另外还要是后面的大于等于前面的:\(s[i] - s[i - 1] >= 0\)

​ 因为相邻的最多只差一,所以:\(s[i] - s[i - 1] <= 1\)

​ 还有:dij一定不能用在带有负边权的图中!!!这道题只能用SPFA。(我傻不愣登的调了一上午dij)

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>

#define int long long

using namespace std;

inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}

const int N = 5e5 + 5, inf = 1e9;
int n, maxn, minn, cnt;
int in[N], vis[N], dis[N], head[N];
struct edge { int to, nxt, val; } e[N << 2];

void add(int x, int y, int z) {
    e[++cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y; e[cnt].val = z;
}

void run_dij() {
    memset(dis, 128, sizeof(dis));
    queue <int> q;
    q.push(minn); dis[minn] = 0;
    while(!q.empty()) {
        int x = q.front(); q.pop(); in[x] = 0;
        for(int i = head[x]; i ; i = e[i].nxt) {
            int y = e[i].to;
            if(dis[y] < dis[x] + e[i].val) {
                dis[y] = dis[x] + e[i].val;
                if(!in[y]) in[y] = 1, q.push(y);
            }
        }
    }
}

signed main() {

    n = read(); maxn = -inf; minn = inf;
    for(int i = 1, x, y, z;i <= n; i++) {
        x = read() + 1, y = read() + 1, z = read(), add(x - 1, y, z);
        maxn = max(maxn, max(x - 1, y));
        minn = min(minn, min(x - 1, y));
    }
    for(int i = minn;i <= maxn; i++) {
        if(i != minn) add(i - 1, i, 0), add(i, i - 1, -1);
    }

    run_dij();

    printf("%lld", dis[maxn]);

    return 0;
}
posted @ 2020-09-19 11:40  C锥  阅读(72)  评论(0编辑  收藏  举报