• BZOJ 1283: 序列 (最大费用流)


    题意

    有n个正整数,要选取里面的一些数,在保证每m个连续的数中最多选k个的情况下,使得得到的值最大.

    分析

    我们可以把问题先转化为选k次,每一次每m个数只能选一个.那么根据贪心的策略,每m个里一定会选一个.那么先建一个源点S,一个汇点T,连边就先用容量为k,费用为0的边把S,数组,T顺次连起来,然后每一个位置i向i+m(如果>n就连向T)连一条容量为1,费用为a[i]的边.做最大费用流即可.

    CODE

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN = 1005;
    const int MAXM = 5005;
    const int inf = 1e9;
    int n, m, k, S, T, fir[MAXN], info[MAXN], cnt;
    struct edge { int to, nxt, c, w; }e[MAXM];
    inline void add(int u, int v, int cc, int ww) {
    	e[cnt] = (edge) { v, fir[u], cc, ww }, fir[u] = cnt++;
    	e[cnt] = (edge) { u, fir[v], 0, -ww }, fir[v] = cnt++;
    }
    int dis[MAXN], Ans; deque<int>q;
    bool inq[MAXN], vis[MAXN];
    inline bool spfa() {
    	memset(dis, 0x3f, sizeof dis);
    	q.push_back(T); dis[T] = 0;
    	while(!q.empty()) {
    		int u = q.front(), v; q.pop_front(); inq[u] = 0;
    		for(int i = fir[u]; ~i; i = e[i].nxt)
    			if(e[i^1].c && dis[v=e[i].to] > dis[u] + e[i^1].w) {
    				dis[v] = dis[u] + e[i^1].w;
    				if(!inq[v]) {
    					inq[v] = 1;
    					if(!q.empty() && dis[v] < dis[q.front()]) q.push_front(v);
    					else q.push_back(v);
    				}
    			}
    	}
    	return dis[S] < inf;
    }
    int aug(int u, int Max) {
    	if(u == T) { Ans += Max * dis[S]; return Max; }
    	int delta, flow = 0, v;
    	vis[u] = 1;
    	for(int &i = info[u]; ~i; i = e[i].nxt)
    		if(e[i].c && dis[v=e[i].to] + e[i].w == dis[u] && !vis[v]) {
    			delta = aug(v, min(Max-flow, e[i].c));
    			e[i].c -= delta, e[i^1].c += delta;
    			if((flow+=delta) == Max) break;
    		}
    	vis[u] = 0;
    	return flow;
    }
    inline int dinic() {
    	Ans = 0;
    	while(spfa())
    		memcpy(info, fir, (T+1)<<2), aug(S, inf);
    	return Ans;
    }
    int main () {
    	memset(fir, -1, sizeof fir);
    	scanf("%d%d%d", &n, &m, &k);
    	S = 0, T = n+1;
    	for(int i = 1, x; i <= n; ++i) {
    		scanf("%d", &x);
    		add(i-1, i, k, 0);
    		add(i, min(i+m, n+1), 1, -x);
    	}
    	add(n, n+1, k, 0);
    	printf("%d
    ", -dinic());
    }
    
  • 相关阅读:
    体温填报APP--流程设计
    构建之法阅读笔记(一)
    家庭记账本(七)
    家庭记账本(六)
    家庭记账本(五)
    家庭记账本(四)
    家庭记账本(三)
    家庭记账本(二)
    家庭记账本(一)
    20210207 BaseAdapter
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039387.html
Copyright © 2020-2023  润新知