POJ 1201 Intervals
题目大意:
给定 n 个区间 [ai,bi]和 n 个整数 ci。
你需要构造一个整数集合 Z,使得∀i∈[1,n] ,Z 中满足 ai ≤ x ≤ bi 的整数 x 不少于 ci 个。
求这样的整数集合 Z 最少包含多少个数。
思路:
定义d[ x ]表示 0到x最少选择多少个数字,则有 d[bi] - d[ai - 1] >= ci,变形后可得 d[bi] >= d[ai - 1] + ci,最短路径算法中的三角不等式,因此本题目可以用差分约束来解决
除了上述条件外,还有两个隐含的条件,因为d[x]表示的是从0开始到x最少选择几个数字,所以0 <= d[x + 1] - d[x] <= 1
因此我们又得到了两个不等式,用上述不等式建图之后,跑一遍最长路就ok了(当然最短路也可以,最短路的建图和源点汇点的选择会与最长路有所不同)
重点:
如果求x3 - x1的最大值,就可以将上述要求化成x3 - x1 <= t,求 t 的值,而x3 <= x1 + t是最短路中的松弛操作,相当于求x1 到 x3的最短路径,反之,如果求最小值,就是x3 - x1 >= t,相当于x3 >= x1 + t,相当于从x1 到 x3的最长路。
同理,也可以将最大值理解为,x3 - x1 <= t --> x1 - x3 >= -t,即x3 到 x1的最长路,但是这样求出来的是 -t,我们要求 t ,所以求其相反数即可
最长路code
#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int N = 51000 * 3;
int head[N], nex[N], to[N], edge[N];
int d[N];
int cnt, c[N], n;
bool v[N];
struct SPFA {
SPFA() {
mem(head, -1);
mem(nex, -1);
mem(to, -1);
cnt = 0;
mem(c, 0);
mem(v, 0);
mem(d, 0x3f);
for (int i = 0; i < N; i++)d[i] = -d[i];
}
void init() {
SPFA();
}
void add(int x, int y, int z) {
++cnt;
to[cnt] = y;
edge[cnt] = z;
nex[cnt] = head[x];
head[x] = cnt;
}
int spfa(int be, int en) {
c[be]++;
d[be] = 0;
v[be] = 1;
queue<int> q;
q.push(be);
bool f = 1;
while (!q.empty()) {
int t = q.front();
q.pop();
v[t] = 0;
if (c[t] > n) {
f = 0;
break;
}
c[t]++;
for (int i = head[t]; i != -1; i = nex[i]) {
int y = to[i];
int dist = edge[i];
if (d[y] < d[t] + dist) {
d[y] = d[t] + dist;
if (!v[y]) {
v[y] = 1;
q.push(y);
}
}
}
}
if (f)
return d[en];
else
return -1;
}
}sp;
int main()
{
sp.init();
ios::sync_with_stdio(0);
cin >> n;
int be = 0x3f3f3f3f;
int en = -1;
for (int i = 0; i < n; i++) {
int x, y, z;
cin >> x >> y >> z;
// y >= (x - 1) + ci
sp.add(x, y + 1, z);
}
for (int i = 0; i < 50002; i++) {
sp.add(i, i + 1, 0);
sp.add(i + 1, i, -1);
}
cout << sp.spfa(0, 50001) << "\n";
return 0;
}
最短路code
/*
* Test2
*/
#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int N = 51000 * 3;
int head[N], nex[N], to[N], edge[N];
int d[N];
int cnt, c[N], n;
bool v[N];
struct SPFA {
SPFA() {
mem(head, -1);
mem(nex, -1);
mem(to, -1);
cnt = 0;
mem(c, 0);
mem(v, 0);
mem(d, 0x3f);
// for (int i = 0; i < N; i++)d[i] = -d[i];
}
void init() {
SPFA();
}
void add(int x, int y, int z) {
++cnt;
to[cnt] = y;
edge[cnt] = z;
nex[cnt] = head[x];
head[x] = cnt;
}
int spfa(int be, int en) {
c[be]++;
d[be] = 0;
v[be] = 1;
queue<int> q;
q.push(be);
bool f = 1;
while (!q.empty()) {
int t = q.front();
q.pop();
v[t] = 0;
if (c[t] > n) {
f = 0;
break;
}
c[t]++;
for (int i = head[t]; i != -1; i = nex[i]) {
int y = to[i];
int dist = edge[i];
if (d[y] > d[t] + dist) {
d[y] = d[t] + dist;
if (!v[y]) {
v[y] = 1;
q.push(y);
}
}
}
}
if (f)
return d[en];
else
return -1;
}
}sp;
int main()
{
sp.init();
ios::sync_with_stdio(0);
cin >> n;
int be = 0x3f3f3f3f;
int en = -1;
for (int i = 0; i < n; i++) {
int x, y, z;
cin >> x >> y >> z;
// y >= (x - 1) + ci
// sp.add(x, y + 1, z);
sp.add(y + 1, x, -z);
}
for (int i = 0; i < 50002; i++) {
sp.add(i, i + 1, 1);
sp.add(i + 1, i, 0);
}
cout << -sp.spfa(50001, 0) << "\n";
return 0;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12861981.html

浙公网安备 33010602011771号