cychester

POJ 1201 Intervals - 差分约束

description

有$n$个区间 $[a_i, b_i]$, 以及$c_i$, 有一个整数集合Z, 要求对于每个区间$[a_i, b_i] 中的数不少于$c_i$个。

 

Solution

设$s_k$ 表示前k个数至少要选几个, 显然有$s[b_i] - s[a_i - 1] >= c_i$, 然后就是一个很显然的差分约束

另外还需满足: $s_{k+1} - s_k >= 0$, $s_{k+1} - s_k <= 1$

所以从$a_i - 1$ 向 $b_i$连一条长度为$c_i$的边

从$k$向$k+1$连长度为$0$ 的边

从$k+1$向$k$连长度为$-1$的边

跑一遍最长路即可求出答案

 

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 #define rd read()
 6 #define rep(i,a,b) for(int i = (a); i <= (b); ++i)
 7 #define per(i,a,b) for(int i = (a); i >= (b); --i)
 8 using namespace std;
 9 
10 const int N = 5e5 + 1e4;
11 const int M = 3e6;
12 const int inf = ~0U >> 2;
13 
14 int n, dis[N], vis[N], cnt[N];
15 int tot, head[N];
16 
17 queue<int> q;
18 
19 struct edge {
20     int nxt, to, val;
21 }e[M];
22 
23 int read() {
24     int X = 0, p = 1; char c = getchar();
25     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
26     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
27     return X * p;
28 }
29 
30 void add(int u, int v, int val) {
31     e[++tot].to = v;
32     e[tot].val = val;
33     e[tot].nxt = head[u];
34     head[u] = tot;
35 }
36 
37 int spfa() {
38     q.push(0);
39     dis[0] = 0;
40     for(int u; !q.empty();) {
41         u = q.front(); q.pop();
42         vis[u] = 0;
43         for(int i = head[u]; i; i = e[i].nxt) {
44             int nt = e[i].to;
45             if(dis[nt] >= dis[u] + e[i].val) continue;
46             dis[nt] = dis[u] + e[i].val;
47             if(!vis[nt]) vis[nt] = 1, q.push(nt);
48         }
49     }
50     return dis[(int)5e5 + 1];
51 }
52 
53 int main()
54 {
55     n = rd;
56     for(int i = 0; i <= 5e5; ++i) {
57         add(i, i + 1, 0); add(i + 1, i, -1);
58     }
59     memset(dis, -1, sizeof(dis));
60     rep(i, 1, n) {
61         int a = rd, b = rd, c = rd;
62         add(a, b + 1, c);
63     }
64     printf("%d\n", spfa());
65 }
View Code

 

posted on 2018-09-02 16:17  cychester  阅读(97)  评论(0编辑  收藏  举报

导航