差分约束中的两类问题:
1.
1.
1.某某条件下(不等式)最小值
一般是将不等式化为
x
i
−
x
j
>
=
k
x_i-x_j>=k
xi−xj>=k的形式,建边的时候是
j
→
i
j\rightarrow i
j→i的有向边,权值为
k
k
k,给定起点终点然后跑一遍最长路。
2.
2.
2.某某条件下(不等式)最大值
一般是将不等式化为
x
i
−
x
j
<
=
k
x_i-x_j<=k
xi−xj<=k的形式,建边的时候是
j
→
i
j\rightarrow i
j→i的有向边,权值为
k
k
k,给点起点终点然后跑一遍最短路。
题意:
给你 n n n个区间 [ a i , b i ] [a_i,b_i] [ai,bi]和对应的 c i c_i ci, c i c_i ci表示在这个区间内必须有至少 c i c_i ci个整点,整点不能重复。最后问一个最短的区间长度能使得这些条件满足。
分析:
假定
d
[
i
]
d[i]
d[i]表示从题目给定的最小值点到
i
i
i点用几个整点。
那么有
I
.
I.
I.
d
[
b
]
−
d
[
a
−
1
]
>
=
c
d[b]-d[a-1]>=c
d[b]−d[a−1]>=c
I
I
.
II.
II.
d
[
i
+
1
]
−
d
[
i
]
<
=
1
d[i+1]-d[i]<=1
d[i+1]−d[i]<=1
(
(
(再转化成
x
i
−
x
j
>
=
k
x_i-x_j>=k
xi−xj>=k的形式)
I
I
I
.
III.
III.
d
[
i
+
1
]
−
d
[
i
]
<
=
0
d[i+1]-d[i]<=0
d[i+1]−d[i]<=0
假设输入
a
,
b
,
c
a,b,c
a,b,c,建图就是
a
d
d
e
d
g
e
(
a
−
1
,
b
,
c
)
addedge(a-1,b,c)
addedge(a−1,b,c),因为
a
−
1
a-1
a−1可能是
−
1
-1
−1,所以平移移位
a
d
d
e
d
g
e
(
a
,
b
+
1
,
c
)
addedge(a,b+1,c)
addedge(a,b+1,c)即可。
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
const int maxn = 5e5 + 5;
const int maxm = 100 + 5;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;//19260817
const double pi = acos(-1.0);
int n, a, b, c, cnt, MIN, MAX, head[maxn], dis[maxn], vis[maxn];
struct node{
int to, val, next;
}edge[maxn * 20];
void addedge(int u, int v, int w){
edge[++cnt].to = v;
edge[cnt].val = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
void spfa(int st){
memset(dis, -inf, sizeof dis);
dis[st] = 0;
queue<int> q;
q.push(st);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u]; i; i = edge[i].next){
int v = edge[i].to, w = edge[i].val;
if(dis[v] < dis[u] + w){
dis[v] = dis[u] + w;
if(!vis[v]){
q.push(v);
vis[v] = 1;
}
}
}
}
printf("%d\n", dis[MAX]);
}
int main(){
scanf("%d", &n);
MIN = inf, MAX = -inf;
for(int i = 1; i <= n; i++){
scanf("%d %d %d", &a, &b, &c);
addedge(a, b + 1, c);
MIN = min(MIN, a);
MAX = max(MAX, b + 1);
}
for(int i = MIN; i < MAX; i++){
addedge(i, i + 1, 0);
addedge(i + 1, i, -1);
}
spfa(MIN);
return 0;
}