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;
}