BZOJ-2465 [中山市选2009]小球(最大费用最大流)
题目描述
给定 \(n(1\leq n\leq 200)\) 个不同颜色的球,每个球 \(i\) 都有一个分数 \(p_i(1\leq p_i\leq 10^6)\),同时有 \(m(0\leq m\leq 200)\) 个瓶子,每个瓶子 \(j\) 都有容量 \(c_j(0\leq c_j\leq 200)\)(最多能装多少个球) 和分数上界 \(q_j(1\leq q_j\leq 10^6)\)(放进该瓶子的每个球的分数都不能超过\(q_j\))。计算最多能放多少个球到这些瓶子里,以及在这个前提下,放进瓶子里面的所有球的最大分数总和。
分析
源点 \(S\) 向每个球 \(i\) 连一条容量为 \(1\),费用为 \(p_i\) 的边;若 \(p_i\leq q_j\),每个球 \(i\) 向每个瓶子 \(j\) 连一条容量为 \(1\),费用为 \(0\) 的边;每个瓶子 \(j\) 向汇点 \(T\) 连一条容量为 \(c_j\),费用为 \(0\) 的边。跑一次 \(\text{SPFA}\) 找增广路就相当于放了一个球。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=5010,M=200010;
int p[1010],c[1010],q[1010];
struct Edge
{
int to;
int Next;
int dis;
int cost;
}edge[M];
int head[N],dist[N],incf[N],pre[N],vis[N];
int n,m,S,T,num_edge,maxflow,maxcost;
void add_edge(int from,int to,int dis,int cost)
{
edge[++num_edge].to=to;
edge[num_edge].dis=dis;
edge[num_edge].cost=cost;
edge[num_edge].Next=head[from];
head[from]=num_edge;
}
bool SPFA()
{
queue<int> Q;
memset(dist,0xcf,sizeof(dist));
memset(vis,0,sizeof(vis));
Q.push(S);
dist[S]=0;
vis[S]=1;
incf[S]=1<<30;
while(!Q.empty())
{
int x=Q.front();
vis[x]=0;
Q.pop();
for(int i=head[x];i;i=edge[i].Next)
{
if(!edge[i].dis)
continue;
int y=edge[i].to,z=edge[i].cost;
if(dist[y]<dist[x]+z)
{
dist[y]=dist[x]+z;
incf[y]=min(incf[x],edge[i].dis);
pre[y]=i;
if(!vis[y])
{
vis[y]=1;
Q.push(y);
}
}
}
}
if(dist[T]==0xcfcfcfcf)
return false;
return true;
}
void update()
{
int x=T;
while(x!=S)
{
int i=pre[x];
edge[i].dis-=incf[T];
edge[i^1].dis+=incf[T];
x=edge[i^1].to;
}
maxflow+=incf[T];
maxcost=maxcost+dist[T]*incf[T];
}
int main()
{
while(cin>>n>>m&&n&&m)
{
memset(head,0,sizeof(head));
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
for(int i=1;i<=m;i++)
scanf("%d %d",&c[i],&q[i]);
S=n+m+1;
T=n+m+2;
num_edge=1;
for(int i=1;i<=n;i++)
{
add_edge(S,i,1,p[i]);
add_edge(i,S,0,-p[i]);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(p[i]<=q[j])
{
add_edge(i,j+n,1,0);
add_edge(j+n,i,0,0);
}
}
}
for(int j=1;j<=m;j++)
{
add_edge(j+n,T,c[j],0);
add_edge(T,j+n,0,0);
}
maxflow=0;maxcost=0;
while(SPFA())
update();
cout<<maxflow<<" "<<maxcost<<endl;
}
return 0;
}
posted on 2020-12-02 12:36 DestinHistoire 阅读(55) 评论(0) 编辑 收藏 举报