BZOJ 1283: 序列 最大费用费用流

来源:互联网 发布:苹果7数据 编辑:程序博客网 时间:2024/04/19 10:56

题意:给定一个长度为n的序列,要求选一些数,使得任意一个长度为m个区间中最多选k个数,求最大的和

解法: 论文上的题目 《浅析信息学中的“分”与“合”》

最大费用最大流

把这个序列用流量为k费用为0的边连成一条直线 然后第i个点向第i+m个点连一条费用为a[i]流量为1的边

跑最大费用最大流即可

反正具体看论文吧,注意论文是拆了点的,但是这个模型拆和不拆是等效的。

//BZOJ 1283 最大费用最大流#include <bits/stdc++.h>using namespace std;const int maxn = 1010;const int maxm = 100010;const int inf = 0x3f3f3f3f;struct node{    int st, en, flow, cost, next;    node(){}    node(int st, int en, int flow, int cost, int next) : st(st), en(en), flow(flow), cost(cost), next(next){}}E[maxm];int p[maxn], num;void init(){    memset(p, -1, sizeof(p));    num = 0;}void add(int st, int en, int flow, int cost){    E[num] = node(st,en,flow,cost,p[st]);    p[st]=num++;    E[num] = node(en,st,0,-cost,p[en]);    p[en]=num++;}int pre[maxn], dis[maxn];bool fg[maxn];bool spfa(int st, int en){    for(int i=0; i<=en; i++)        fg[i]=0, dis[i]=-1, pre[i]=-1;    queue<int>q;    q.push(st);    fg[st]=1;    dis[st]=1;    while(!q.empty()){        int u = q.front(); q.pop();        fg[u]=0;        for(int i=p[u];~i;i=E[i].next){            int v = E[i].en;            if(E[i].flow&&dis[v]<dis[u]+E[i].cost){                dis[v] = dis[u]+E[i].cost;                pre[v] = i;                if(!fg[v]){                    fg[v]=1;                    q.push(v);                }            }        }    }    return dis[en] != -1;}int solve(int st, int en){    int ans = 0;    while(spfa(st,en))    {        int d = inf;        for(int i = pre[en]; ~i; i = pre[E[i].st]) d = min(d, E[i].flow);        for(int i = pre[en]; ~i; i = pre[E[i].st]){            ans += d * E[i].cost;            E[i].flow -= d;            E[i^1].flow += d;        }    }    return ans;}int a[maxn];int main(){    int n, m, k;    scanf("%d%d%d", &n,&m,&k);    init();    int st, en;    st = 0, en = n+1;    for(int i=1; i<=n; i++){        scanf("%d",&a[i]);        add(i-1,i,k,0);        if(i+m<=n) add(i,i+m,1,a[i]);        else add(i,en,1,a[i]);    }    int ans = solve(st, en);    printf("%d\n", ans);    return 0;}
0 0