他说每个点都不能被k个区间覆盖。
也就是说每个点最大流量为k,所以i-1到i的流量为k,费用为0.
我们在把输入数据的区间放进去,费用取负数。
源点指向1,n指向汇点,流量都为k。
如果有一个1-4的区间,我们选择了,之后1肯定被占用了1个流量,1一旦被占用了,代表着2,3都被占用了。
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 450;
struct Edge { int from, to, cap, flow, cost; };
vector<Edge> edges;
vector<int> G[maxn];
int inque[maxn]; //spfa
int d[maxn]; //源点到当前点的最短路
int p[maxn]; //入弧编号
int a[maxn]; //可改进量
void init(int n)
{
for(int i=0; i<=n; i++) G[i].clear();
edges.clear();
}
void add_edge(int from, int to, int cap, int cost)
{
edges.push_back((Edge){from, to, cap, 0, cost});
edges.push_back((Edge){to, from, 0, 0, -cost});
int m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool spfa(int s, int t, int &flow, long long &cost)
{
memset(d, 0x3f, sizeof(d));
memset(inque, 0, sizeof(inque));
d[s] = 0; inque[s] = 1;
a[s] = inf; p[s] = 0;
queue<int> que;
que.push(s);
while(!que.empty()){
int u = que.front(); que.pop();
inque[u] = 0;
for(int i=0; i<G[u].size(); i++){
Edge e = edges[G[u][i]];
if(e.cap>e.flow && d[e.to]>d[u]+e.cost){
d[e.to] = d[u] + e.cost;
if(!inque[e.to]) que.push(e.to), inque[e.to]=1;
p[e.to] = G[u][i]; //e.to的入弧编号
a[e.to] = min(a[u], e.cap-e.flow); //更新可改进量
}
}
}
if(d[t] == inf) return false;
flow += a[t];
cost += (long long)a[t]*(long long)d[t];
for(int u=t; u!=s; u=edges[p[u]].from){
edges[p[u]].flow += a[t];
edges[p[u]^1].flow -= a[t];
}
return true;
}
int MCMF(int s, int t, long long &cost)
{
int flow = 0; cost = 0;
while(spfa(s, t, flow, cost));
return flow;
}
int aa[250], bb[250], ww[250];
vector<int> x;
int main() {
int T;
scanf("%d", &T);
while(T--) {
int N, K;
scanf("%d%d", &N, &K);
x.clear();
for(int i=0; i<N; i++) {
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
x.push_back(a);
x.push_back(b);
aa[i] = a;
bb[i] = b;
ww[i] = w;
}
sort(x.begin(), x.end());
x.erase(unique(x.begin(), x.end()), x.end());
//debug
//for(int i=0; i<x.size(); i++)
// cout<<x[i]<<' ';
//cout<<endl;
int m = x.size();
int s = m, t = m+1;
init(m+1);
add_edge(s, 0, K, 0);
add_edge(m-1, t, K, 0);
for(int i=0; i+1<x.size(); i++) {
add_edge(i, i+1, K, 0);
}
for(int i=0; i<N; i++) {
int u = find(x.begin(), x.end(), aa[i]) - x.begin();
int v = find(x.begin(), x.end(), bb[i]) - x.begin();
add_edge(u, v, 1, -ww[i]);
}
long long cost = 0;
MCMF(s, t, cost);
cout<<-cost<<endl;
}
return 0;
}
离散化方法:
//两个端点放到一个容器中
x.push_back(a);
x.push_back(b);
//保存原本数据
aa[i] = a;bb[i] = b;
ww[i] = w;
//容器排序,去除相同点。
sort(x.begin(), x.end());x.erase(unique(x.begin(), x.end()), x.end());
//取值,对于第i个,也就是aa[i],bb[i],ww[i]
int u = find(x.begin(), x.end(), aa[i]) - x.begin();int v = find(x.begin(), x.end(), bb[i]) - x.begin();