最大费用最大流
如何构图?
设源点为
S
,汇点为
将所有的端点离散化,
S
点向第一个点连边,每个点向下一个点连边,最后一个点向
对于每条线段,从左端点向右端点连边,流量为 1 <script type="math/tex" id="MathJax-Element-7">1</script>,费用为其长度。
这样就限制了选择的线段数量,同时使得总长度最大。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <utility>
#include <iostream>
#include <algorithm>
template<class Num>void read(Num &x)
{
char c; int flag = 1;
while((c = getchar()) < '0' || c > '9')
if(c == '-') flag *= -1;
x = c - '0';
while((c = getchar()) >= '0' && c <= '9')
x = (x<<3) + (x<<1) + (c-'0');
x *= flag;
return;
}
template<class Num>void write(Num x)
{
if(x < 0) putchar('-'), x = -x;
static char s[20];int sl = 0;
while(x) s[sl++] = x%10 + '0',x /= 10;
if(!sl) {putchar('0');return;}
while(sl) putchar(s[--sl]);
}
#define REP(__i,__start,__end) for(int __i = (__start); __i <= (__end); __i++)
const int maxn = 510, node = maxn << 1, edgenum = node << 2, INF = 0x3f3f3f3f;
int n, _k;
struct Edge
{
int v, cap, cost, next;
Edge(int v = 0,int cap = 0,int cost = 0,int next = 0):v(v), cap(cap), cost(cost), next(next){}
}edge[edgenum];
#define St first
#define Ed second
std::pair<int, int> seg[maxn];
int bowl[node], bsize;
int head[node], el = 1, S, T, ind;
int dist[node], fr[node], fd[node];
void newedge(int u,int v,int cap,int cost)
{
edge[++el] = Edge(v, cap, cost, head[u]), head[u] = el;
edge[++el] = Edge(u, 0, -cost, head[v]), head[v] = el;
}
bool SPFA()
{
static int line[node];
static bool hash[node];
int f = 0, r = 0;
REP(i, 1, ind) dist[i] = -INF, fr[i] = fd[i] = 0;
dist[S] = 0, line[r] = S, r = (r + 1)%node;
hash[S] = true;
while(f != r)
{
int x = line[f], p, calc;
line[f] = 0, f = (f + 1)%node;
hash[x] = false;
for(int i = head[x]; i; i = edge[i].next)
if(edge[i].cap)
{
p = edge[i].v, calc = dist[x] + edge[i].cost;
if(calc > dist[p])
{
dist[p] = calc, fr[p] = x, fd[p] = i;
if(!hash[p])
{
if(dist[p] <= dist[line[f]])
f = (f - 1 + node)%node, line[f] = p;
else
line[r] = p, r = (r + 1)%node;
hash[p] = true;
}
}
}
}
return (dist[T] > -INF);
}
int change(int a,int flow)
{
if(a != S)
{
flow = std::min(flow, edge[fd[a]].cap);
flow = change(fr[a], flow);
edge[fd[a]].cap -= flow;
edge[fd[a]^1].cap += flow;
}
return flow;
}
void init()
{
int u, v;
read(n), read(_k);
REP(i, 1, n)
{
read(u), read(v);
seg[i] = std::make_pair(u, v);
}
}
void prework()
{
REP(i, 1, n)
{
bowl[i<<1] = seg[i].St;
bowl[(i<<1) - 1] = seg[i].Ed;
}
std::sort(bowl + 1, bowl + (n << 1) + 1);
bsize = std::unique(bowl + 1, bowl + (n << 1) + 1) - (bowl + 1);
S = bsize + 1, T = bsize + 2, ind = T;
REP(i, 1, bsize - 1) newedge(i, i + 1, INF, 0);
newedge(S, 1, _k, 0), newedge(bsize, T, _k, 0);
REP(i, 1, n)
{
int len = seg[i].Ed - seg[i].St;
seg[i].St = std::lower_bound(bowl + 1, bowl + bsize + 1, seg[i].St) - bowl;
seg[i].Ed = std::lower_bound(bowl + 1, bowl + bsize + 1, seg[i].Ed) - bowl;
newedge(seg[i].St, seg[i].Ed, 1, len);
}
}
int solve()
{
int maxcost = 0, maxflow = 0;
while(SPFA())
{
maxcost += dist[T];
maxflow += change(T, INF);
}
return maxcost;
}
int main()
{
freopen("interv.in","r",stdin);
freopen("interv.out","w",stdout);
init(), prework(), write(solve());
fclose(stdin);
fclose(stdout);
return 0;
}