2200专项:I. Olympiad in Programming and Sports(费用流 ab值选择)

原题: http://codeforces.com/problemset/problem/730/I

题意:

每个人有ab值,现在选择x个人取a,y个人取b,求和的最大值。

解析:

dp不会,直接费用流即可。ab两点连汇点,流量为x和y,每个人的点连向ab,流量1,费用(-其值),跑一下即可。

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
#define LL long long
#define pill pair<int,int>

const int inf=0x3f3f3f3f;
const LL infll=1e18;
const int N=4010,M=202020;

int head[N],nex[M],to[M],val[M],cost[M],now;
void add(int a,int b,int v,int c){
    to[++now]=b;val[now]=v;cost[now]=c;nex[now]=head[a];head[a]=now;
    to[++now]=a;val[now]=0;cost[now]=-c;nex[now]=head[b];head[b]=now;
}

//*********************

int sp,ep,dis[N];

bool vis[N];
int pre[N];

bool SPFA(int &flow,int &cos){
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    for(int i=0;i<N;i++)dis[i]=inf;

    queue<int>Q;
    dis[sp]=0;vis[sp]=1;Q.push(sp);
    int d=inf;
    while(!Q.empty()){
        int p=Q.front();Q.pop();
        vis[p]=0;
        for(int i=head[p];~i;i=nex[i]){
            int u=to[i];
            if(val[i]>0&&dis[u]-cost[i]>dis[p]){
                dis[u]=dis[p]+cost[i];
                pre[u]=i;
                if(!vis[u]){
                    vis[u]=1;Q.push(u);
                }
            }
        }
    }
    if(dis[ep]==inf)return 0;
    for(int i=pre[ep];~i;i=pre[to[i^1]]){
        d=min(d,val[i]);
    }
    for(int i=pre[ep];~i;i=pre[to[i^1]]){
        val[i]-=d;
        val[i^1]+=d;
        cos+=cost[i]*d;
    }
    flow+=d;
    return 1;
}

int MinCost(){
    int flow=0,cost=0;
    while(SPFA(flow,cost)){}
    return cost;
}

//***********************

int n,m,k,W;
struct node{
    int id,s,t,v,op;
    bool operator < (const node &r)const{
        return s<r.s;
    }
}e[201];

void init(){
    now=-1;//要求第一条边为0
    memset(head,-1,sizeof(head));
}

//sp -p-> point --> ep
int x[N],y[N];
int main(){
    int n,a,b;
    scanf("%d%d%d",&n,&a,&b);
    init();
    sp=0;ep=N-1;
    for(int i=1;i<=n;i++){
        scanf("%d",x+i);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",y+i);
    }
    for(int i=1;i<=n;i++)add(0,i,1,0),add(i,n+1,1,-x[i]),add(i,n+2,1,-y[i]);
    add(n+1,ep,a,0);
    add(n+2,ep,b,0);

    int ans=MinCost();
    printf("%d\n",-ans);
    for(int i=head[n+1];~i;i=nex[i]){
        int u=to[i];
        if(u>=1&&u<=n&&val[i]==1)printf("%d ",u);
    }
    printf("\n");
    for(int i=head[n+2];~i;i=nex[i]){
        int u=to[i];
        if(u>=1&&u<=n&&val[i]==1)printf("%d ",u);
    }
    printf("\n");
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/90550133