HDU多校第三场 1009 K subsequence —— 费用流

题目链接:点我啊╭(╯^╰)╮

题目大意:

    长度为 n n 的序列,最多取 k k
    每次可以从中取走一个不下降子序列
    求最大的 a i a_i 总和

解题思路:

在这里插入图片描述

核心:费用流模板题

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int INF = INT_MAX;
const int maxn = 4e3 + 5;

struct edge {
	int to, cap, cost, rev;
	edge() {}
	edge(int _to, int _cap, int _cost, int _rev):\
		to(_to), cap(_cap), cost(_cost), rev(_rev) {}
};

struct Min_Cost_Max_Flow {
	int V, h[maxn], dis[maxn], prev[maxn], pree[maxn];
	vector <edge> G[maxn];
	//调用前初始化
	void init(int n) {
		V = n;
		for(int i=0; i<=V; i++) G[i].clear();
	}
	void add_edge(int from, int to, int cap, int cost) {
		G[from].push_back(edge(to, cap, cost, G[to].size()));
		G[to].push_back(edge(from, 0, -cost, G[from].size()-1));
	}
	//flow是自己传进去的变量,就是最后的最大流,返回的是最小费用
	int min_cost_max_flow(int s, int t, int f, int &flow) {
		int res = 0; fill(h, h+V+1, 0);
		while(f) {
			priority_queue<pii, vector<pii>, greater<pii> > q;
			fill(dis, dis+V+1, INF);
			dis[s] = 0; q.push(pii(0, s));
			while(!q.empty()) {
				pii now = q.top(); q.pop();
				int v = now.second;
				if(dis[v] < now.first) continue;
				for(int i=0; i<G[v].size(); ++i) {
					edge &e = G[v][i];
					if(e.cap>0 && dis[e.to]>dis[v]+e.cost+h[v]-h[e.to]) {
						dis[e.to] = dis[v]+e.cost+h[v]-h[e.to];
						prev[e.to] = v; pree[e.to] = i;
						q.push(pii(dis[e.to], e.to));
					}
				}
			}
			if(dis[t] == INF) break;
			for(int i=0; i<=V; ++i) h[i] += dis[i];
			int d = f;
			for(int v=t; v!=s; v=prev[v]) d = min(d, G[prev[v]][pree[v]].cap);
			f -= d; flow += d; res += d * h[t];
			for(int v=t; v!=s; v=prev[v]) {
				edge &e = G[prev[v]][pree[v]];
				e.cap -= d; G[v][e.rev].cap += d;
			}
		}
		return res;
	}
};

int T, n, k, a[maxn], flow;
Min_Cost_Max_Flow MCMF;
int main() {
	scanf("%d", &T);
	while(T--){
		scanf("%d%d", &n, &k);
		int s = 0, t = 2 * n + 1;
		MCMF.init(t);
		for(int i=1; i<=n; i++){
			scanf("%d", a+i);
			MCMF.add_edge(i, i+n, 1, -a[i]);
			MCMF.add_edge(s, i, 1, 0);
			MCMF.add_edge(i+n, t, 1, 0);
			for(int j=1; j<i; j++)
				if(a[j] <= a[i]) MCMF.add_edge(j+n, i, 1, 0);
		}
		printf("%d\n", -MCMF.min_cost_max_flow(s, t, k, flow));
	}
}
发布了221 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Scar_Halo/article/details/102904063