【题意】:给出一个数集合Z与n个区间,每个区间表示为[ai,bi,ci].[ai,bi,ci]表示闭区间[ai,bi]与Z至少有ci个相同的数,求出数集Z可能的最少元素个数。
 
【题解】:从题目中,我们可以抽象出一大堆约束条件,并且ci的定义上明显包含着不等关系。于是可以利用差分约束模型来解决。
             •(1) [ai,bi,ci]中,ai和bi最小可以取到0,为了方便,把所有的ai,bi都+1.
             •(2) 定义d[i]为闭区间[1,i]中与集合Z中共同元素的个数.要求Z的元素个数最少,就是要求d[max{bi}]-d[0]最小.
             •(3) 分析不等关系:
                  对于[ai,bi,ci],有d[bi]-d[ai-1] >= ci
                  对于每个i,有1 >= d[i]-d[i-1] >= 0

【代码】:
 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "queue"
 5 using namespace std;
 6 const int inf = 1 << 30;
 7 #define maxn 50500
 8 #define maxm 500000
 9 int n, m, l, r;
10 int eh[maxn], tot, dist[maxn];
11 bool visit[maxn];
12 struct Edge {
13     int u, v, w, next;
14 }et[maxm];
15 
16 void init() {
17     tot = 0;
18     memset(eh, -1sizeof(eh));
19 }
20 
21 void addedge(int u, int v, int w) {
22     Edge e = {u, v, w, eh[u]};
23     et[tot] = e;
24     eh[u] = tot++;
25 }
26 
27 void spfa(int s) {
28     queue<int> que;
29     fill(&dist[0], &dist[maxn], -inf);
30     memset(visit, falsesizeof(visit));
31     dist[s] = 0, visit[s] = true;
32     que.push(s);
33     while(!que.empty()) {
34         int u = que.front();
35         que.pop();
36         visit[u] = false;
37         for(int i = eh[u]; i !=- 1; i = et[i].next) {
38             int v = et[i].v, w = et[i].w;
39             if(dist[v] < dist[u] + w) {
40                 dist[v] = dist[u] + w;
41                 if(!visit[v]) {
42                     que.push(v);
43                     visit[v] = true;
44                 }
45             }
46         }
47     }
48 }
49 
50 int main() {
51     int a, b, c;
52     while(~scanf("%d"&n)) {
53         init();
54         r = 0;
55     //    l = inf;
56         for(int i = 0; i < n; i++) {
57             scanf("%d%d%d"&a, &b, &c);
58             r = max(r, ++b);
59     //        l = min(l, a);
60             addedge(a, b, c);
61         }
62         for(int i = 1; i <= r; i++) {
63             addedge(i - 1, i, 0);
64             addedge(i, i - 1-1);
65         }
66         spfa(0);
67         printf("%d\n", dist[r]);
68     }
69     return 0;
70 }