传送门
对于每个点拆为入点和出点,连接入点到出点费用为负的点权,流量为1,源点SS连接所有点入点,所有点出点连接汇点T,流量为1,费用为0,对于每个点ai,往后面找最多100个权值大于等于ai的 j 点(别问为啥100个,玄学),i 的出点连接 j 的入点,最后超级源S连接SS,流量为k,费用为0,然后跑一遍费用流即可。
#include
//#define int long long
using namespace std;
const int maxn = 4020;
const int inf = 0x3f3f3f3f;
struct Edge
{
int from,to,cap,flow,cost;
Edge(int a,int b,int c,int d,int e)
{
from = a,to = b,cap = c,flow = d,cost = e;
}
};
struct MCMF
{
int n, m;
vectoredges;
vectorG[maxn];
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn];
void Init(int n)
{
this -> n = 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));
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool bellman(int s,int t,int& flow,int& cost)
{
for(int i = 0;i <= n; i++)
d[i] = inf,inq[i] = 0;
d[s] = 0;inq[s] = 1;p[s] = 0;a[s] = inf;
queueQ;
Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
inq[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;
p[e.to] = G[u][i];
a[e.to] = min(a[u],e.cap - e.flow);
if(!inq[e.to])
{
Q.push(e.to);
inq[e.to] = 1;
}
}
}
}
if(d[t] == inf)
return false;
flow += a[t];
cost += d[t] * a[t];
int u = t;
while(u != s)
{
edges[p[u]].flow += a[t];
edges[p[u]^1].flow -= a[t];
u = edges[p[u]].from;
}
return true;
}
int minCost(int s,int t)
{
int flow = 0,cost = 0;
while(bellman(s,t,flow,cost));
return cost;
}
}solve;
int a[maxn];
signed main()
{
//freopen("in","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n, &k);
for(int i = 1;i <= n; i++)
scanf("%d",&a[i]);
int s0 = 2 * n + 1,s1 = s0 + 1,t = s1 + 1;
solve.Init(t);
solve.add_edge(s0,s1,k,0);
for(int i = 1;i <= n; i++)
{
solve.add_edge(s1,i,1,0);
solve.add_edge(i,i + n,1,-a[i]);
solve.add_edge(i + n,t,1,0);
}
for(int i = 1;i <= n; i++)
{
for (int j = i + 1, ok = 0; j <= n && ok <= 100; j++)
{
if (a[j] >= a[i])
ok++, solve.add_edge(i + n, j, 1, 0);
}
}
printf("%d\n",-solve.minCost(s0,t));
}
return 0;
}