题意
在区间[0,50000]上有一些整点,并且满足n个约束条件:在区间[ui, vi]上至少有ci个整点,问区间[0, 50000]上至少要有几个整点。
思路
差分约束求最小值。把不等式都转换为>=形式,那么显然有xvi >= xui-1 + ci,那么就在约束图中连一条(ui-1, vi, ci)的边;当然不要忘记隐含的不等式:xi >= xi-1 + 0; xi-1 >= xi -1.
建完图后SPFA求最长路径即可
代码
[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <cstring>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, m) for (int i = begin; i < begin+m; i ++)
using namespace std;
const int MAXN = 50005;
const int oo = 0x3fffffff;
struct Edge{
int to;
int w;
Edge(){}
Edge(int _to, int _w){ to = _to; w = _w; }
};
struct Gragh{
vector <Edge> adj[MAXN];
queue <int> q;
int vn;
int dist[MAXN], inq_num[MAXN];
bool inq[MAXN];
void init(int n){
vn = n;
for (int i = 0; i <= n; i ++)
adj[i].clear();
}
//if xj >= xi + c, add (i, j, c)
void add_edge(int u, int v, int w){
adj[u].push_back(Edge(v, w));
}
//spfa calculate longest path
bool solve(int s, int t){
while(!q.empty())
q.pop();
MEM(inq, false); MEM(inq_num, 0); MEM(dist, -1); //Note : dist shouldn't initially be 0
dist[s] = 0; inq[s] = true; inq_num[s] ++; q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
inq[u] = false;
for (int i = 0; i < adj[u].size(); i ++){
int v = adj[u][i].to;
if (dist[v] < dist[u] + adj[u][i].w){
dist[v] = dist[u] + adj[u][i].w;
if (!inq[v]){
inq[v] = true;
inq_num[v] ++;
if (inq_num[v] > vn)
return false;
q.push(v);
}
}
}
}
if (dist[t] < oo){
return true;
}
}
}spfa;
struct intervals{
int u, v, w;
}inte[MAXN];
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int n;
while(scanf("%d", &n) != EOF){
int maxn = 0;
REP(i, 1, n){
scanf("%d %d %d", &inte[i].u, &inte[i].v, &inte[i].w);
inte[i].u ++, inte[i].v ++;
maxn = max(maxn, inte[i].v);
}
spfa.init(maxn+1);
REP(i, 1, maxn){
spfa.add_edge(i-1, i, 0);
spfa.add_edge(i, i-1, -1);
}
REP(i, 1, n){
spfa.add_edge(inte[i].u-1, inte[i].v, inte[i].w);
}
if (spfa.solve(0, maxn)){
printf("%d\n", spfa.dist[maxn]);
}
}
return 0;
}
[/cpp]