题意:
给定一个数轴上的 n 个区间,要求在数轴上选取最少的点使得第 i 个区间 [ai, bi] 里至少有 ci 个点,使用差分约束系统的解法解决这道题。
思路:
记sum[i]表示数轴上[0,i]之间选点的个数,则对于第i个区间[ai,bi]需要满足sum[bi]-sum[ai-1]>=ci。同时需要保证sum有意义,所以0<=sum[i]-sum[i-1]<=1。
对于不等式xi-xj>=ck,从j到i连一条长度为ck的有向边,然后用dijkstra跑最长路即可。最后的最小解就是sum[max{bi}]。
代码:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N = 50010;
int head[N], tot, vis[N];
long long dis[N];
struct Edge {
int to, next, w;
}e[N];
void add(int x, int y, int ww)
{
e[++tot].next = head[x];
e[tot].to = y;
e[tot].w = ww;
head[x] = tot;
}
void dijkstra(int s)//最长路
{
queue<int> q;
dis[s] = 0;
vis[s] = 1;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = head[u]; i != 0; i = e[i].next) {
int v = e[i].to, w = e[i].w;
if (dis[v] < dis[u] + w) {
dis[v] = dis[u] + w;
if (!vis[v]) {
q.push(v);
vis[v] = 1;
}
}
}
}
}
void ini()
{
memset(head, 0, sizeof(head));
tot = 0;
}
int main()
{
ini();
int n;
cin >> n;
int maxn = -1;
for (int i = 0; i < n; i++)
{
int a, b, c;
cin >> a;
cin >> b;
cin >> c;
add(a, b + 1, c);
if (b + 1 > maxn)
maxn = b + 1;
}
for (int i = 1; i <= maxn; i++)
{
add(i - 1, i, 0);//sum[i]>= sum[i - 1]+0
add(i, i - 1, -1);//sum[i-1]>=sum[i]+(-1)
}
for (int i = 0; i <= maxn; i++)
dis[i] = -1e18, vis[i] = 0;
dijkstra(0);
cout << dis[maxn];
}