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

    xiaoxiao2023-11-07  144

    原题: 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"); }
    最新回复(0)