# HDOJ1384 链式前向星+差分约束系统

Problem Description

You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.

Write a program that:

> reads the number of intervals, their endpoints and integers c1, ..., cn from the standard input,

> computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i = 1, 2, ..., n,

> writes the answer to the standard output

Input

The first line of the input contains an integer n (1 <= n <= 50 000) - the number of intervals. The following n lines describe the intervals. The i+1-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50 000 and 1 <= ci <= bi - ai + 1.

Process to the end of file.

Output

The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i = 1, 2, ..., n.

Sample Input


 

5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1

Sample Output

6

设变量xi表示[0,i-1]中至少选择多少个数，则题目中的条件可以转化为不等式 Xbi+1  -  Xi  >=  ci，再加上隐形条件

0 <=  Xi - Xi-1 <= 1，这样就构造出了完成的差分约束的不等式。（只能说大佬们智商太高，我反正想不到）

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#define MAXN 50010
#define INF 99999999
#define INT_MIN -99999999
#define INT_MAX 99999999
using namespace std;
int n;
int Min = INT_MIN,Max = INT_MAX;
int dis[MAXN];
struct Edge {
int next;
int v;
int w;
}edge[3*MAXN];
queue<int> q;
bool vis[MAXN];
int N;//N条边

// 加边
void AddEdge(int u,int v,int w) {
edge[N].v = v;
edge[N].w = w;
}

// 初始化
void Init() {
Min = INT_MAX,Max = INT_MIN;
while(!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
for(int i = 0;i < MAXN;i++) head[i] = -1;
N = 0;
}

// SPFA求最长路
void SPFA() {
q.push(Min);
dis[Min] = 0;
vis[Min] = true;// 标记入队
for(int i = Min+1;i <= Max;i++) dis[i] = -INF;
while(!q.empty()) {
int front = q.front();
q.pop();
vis[front] = false;
for(int e = head[front];e != -1;e = edge[e].next) {
if(dis[edge[e].v] < dis[front] + edge[e].w) {
dis[edge[e].v] = dis[front] + edge[e].w;
if(vis[edge[e].v] == false) {
q.push(edge[e].v);
vis[edge[e].v] = true;
}
}
}
}
}

int main()
{
int a,b,c;
while(scanf("%d",&n) != EOF) {
Init();
for(int i = 0;i < n;i++) {
scanf("%d%d%d",&a,&b,&c);
Max = max(Max,b+1);
Min = min(Min,a);
}
for(int i = Min;i < Max;i++) {
}

SPFA();// 求最长路
printf("%d\n",dis[Max]);

}

return 0;
}