题意:
给定n个不同颜色的球,每个球都有一个分数,同时有m个瓶子,每个瓶子都有固定的容量。现在,你必须把球放到瓶子里面。请编程计算最多能放多少个球到这些瓶子里。
题解:
认真看题!认真看题!认真看题!
其实是到大水题。
st->每个球(1,0)。球到瓶子(1,p[i]),瓶子到ed(c[i],0)。
然后最大费用流。
code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
struct node{
int x,y,c,d,next,other;
}a[2110000];int len=0,last[1100];
int s[10005],p[10005],q[10005],st,ed;
bool u[10005];
void ins(int x,int y,int c,int d)
{
int k1=++len;
a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d;
a[len].next=last[x];last[x]=len;
int k2=++len;
a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d;
a[len].next=last[y];last[y]=len;
a[k1].other=k2;
a[k2].other=k1;
}
bool spfa()
{
memset(s,-63,sizeof(s));
memset(u,false,sizeof(u));
int l=1,r=2;q[l]=st;s[st]=0;u[st]=true;
while(l!=r)
{
int x=q[l];
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(s[y]<s[x]+a[i].d&&a[i].c>0)
{
s[y]=s[x]+a[i].d;
p[y]=i;
if(!u[y])
{
u[y]=true;
q[r]=y;
r++;if(r>ed+1) r=1;
}
}
}
u[x]=false;
l++;if(l>ed+1) l=1;
}
return s[ed]>-99999999;
}
int flow()
{
int x=ed;
int ans=0,min=-1;
while(x!=st)
{
int i=p[x];
if (a[i].c<min||min==-1) min=a[i].c;
x=a[i].x;
}
x=ed;
while(x!=st)
{
int i=p[x];
a[i].c-=min;
a[a[i].other].c+=min;
x=a[i].x;
ans=ans+a[i].d*min;
}
return ans;
}
int n,m,P[210],C[210],Q[210];
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n==0&&m==0) return 0;
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]);
st=0;ed=n+m+1;
len=0;memset(last,0,sizeof(last));
for(int i=1;i<=n;i++)
{
ins(st,i,1,0);
for(int j=1;j<=m;j++)
if(P[i]<=Q[j]) ins(i,j+n,1,P[i]);
}
for(int i=1;i<=m;i++)
ins(i+n,ed,C[i],0);
int ans=0,num=0;
while(spfa()) ans+=flow(),num++;
printf("%d %d\n",num,ans);
}
}