「网络流 24 题」最长 k 可重区间集
例如开区间 (1,5)(1,5)(1,5),我们认为其长度为:5−1=45 - 1 = 45−1=4
思路
我们先将区间端点离散化,将每一个端点抽象成图上的点,将相邻两个端点之间从编号小的向编号大的连一条有向边,容量为 kkk,费用为 000
然后对于每一个区间 (l,r)(l, r)(l,r) 我们都连边:l→rl \rarr rl→r,容量为 111,费用为 l−rl - rl−r(即区间长度的负数)
这样子建图我们可以保证实数轴上每一个点都至多被包含 kkk 次,因为容量限制了
随后我们只需要建立源点 S→1S \rarr 1S→1, 汇点 n→Tn \rarr Tn→T ,跑最小费用最大流即可
#include<bits/stdc++.h>
#define fore(i,l,r) for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;
const int INF=0x3f3f3f3f;
const long long INFLL=1e18;
typedef long long ll;
struct MCF {
struct Edge {
int v, c, w; //边终点、容量、费用
Edge(int v, int c, int w) : v(v), c(c), w(w) {}
};
const int n;
std::vector<Edge> e;
std::vector<std::vector<int>> g;
std::vector<ll> h, dis;
std::vector<int> pre;
bool dijkstra(int s, int t) {
dis.assign(n + 1, std::numeric_limits<ll>::max());
pre.assign(n + 1, -1);
std::priority_queue<std::pair<ll, int>, std::vector<std::pair<ll, int>>, std::greater<std::pair<ll, int>>> que;
dis[s] = 0;
que.emplace(0, s);
while (!que.empty()) {
ll d = que.top().first;
int u = que.top().second;
que.pop();
if (dis[u] < d) continue;
for (int i : g[u]) {
int v = e[i].v;
int c = e[i].c;
int w = e[i].w;
if (c > 0 && dis[v] > d + h[u] - h[v] + w) {
dis[v] = d + h[u] - h[v] + w;
pre[v] = i;
que.emplace(dis[v], v);
}
}
}
return dis[t] != std::numeric_limits<ll>::max();
}
MCF(int n) : n(n), g(n + 1) {}
void addEdge(int u, int v, int c, int w) {
g[u].push_back(e.size());
e.emplace_back(v, c, w);
g[v].push_back(e.size());
e.emplace_back(u, 0, -w);
}
std::pair<int, ll> flow(int s, int t) {
int flow = 0;
ll cost = 0;
h.assign(n + 1, 0);
while (dijkstra(s, t)) {
for (int i = 1; i <= n; ++i) h[i] += dis[i];
int aug = std::numeric_limits<int>::max();
for (int i = t; i != s; i = e[pre[i] ^ 1].v) aug = std::min(aug, e[pre[i]].c);
for (int i = t; i != s; i = e[pre[i] ^ 1].v) {
e[pre[i]].c -= aug;
e[pre[i] ^ 1].c += aug;
}
flow += aug;
cost += ll(aug) * h[t];
}
return std::make_pair(flow, cost);
}
};
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int n, k;
std::cin >> n >> k;
std::vector<int> vec;
std::vector<std::pair<int, int>> a(n);
fore(i, 0, n){
int l, r;
std::cin >> l >> r;
if(l > r) std::swap(l, r);
a[i] = {l, r};
vec.push_back(l);
vec.push_back(r);
}
std:sort(ALL(vec));
vec.erase(std::unique(ALL(vec)), vec.end());
auto get_id = [&](int x) -> int {
return std::lower_bound(ALL(vec), x) - vec.begin() + 1;
};
MCF mcf(vec.size() + 2);
int S = vec.size() + 1, T = S + 1;
mcf.addEdge(S, 1, k, 0);
for(auto [l, r] : a){
int u = get_id(l), v = get_id(r);
mcf.addEdge(u, v, 1, l - r);
}
fore(i, 1, vec.size()){
int u = vec[i - 1], v = vec[i];
mcf.addEdge(i, i + 1, k, 0);
}
mcf.addEdge(vec.size(), T, k, 0);
std::cout << -mcf.flow(S, T).se;
return 0;
}