bzoj 2465 小球
题目大意:
给定n个不同颜色的球,每个球都有一个分数,同时有m个瓶子,每个瓶子都有固定的容量
必须把球放到瓶子里面 计算最多能放多少个球到这些瓶子里
思路:
开始想的是费用流
超级源向每个球连一条 容量为1,费用为球的分数的边
每个瓶子和它可以装下的球连一条 容量为1,费用为0的边
每个瓶子和汇点连一条 容量为瓶的容量,费用为0的边
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define ll long long 11 #define inf 2139062143 12 #define MAXN 500 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); 19 return x*f; 20 } 21 int n,m,s,t,a[MAXN]; 22 ll ans; 23 struct ZKW 24 { 25 int fst[MAXN],to[MAXN*MAXN],nxt[MAXN*MAXN],val[MAXN*MAXN],cos[MAXN*MAXN],cnt; 26 int dis[MAXN],vis[MAXN],q[MAXN]; 27 void mem() {ans=0,cnt=0;memset(fst,0xff,sizeof(fst));} 28 void add(int u,int v,int w,int c) {nxt[cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w,cos[cnt++]=c;} 29 int spfa() 30 { 31 memset(vis,0,sizeof(vis)); 32 memset(dis,127,sizeof(dis)); 33 int l=1,r=0; 34 q[++r]=t,dis[t]=0,vis[t]=1; 35 while(l<=r) 36 { 37 int x=q[l++]; 38 for(int i=fst[x];i!=-1;i=nxt[i]) 39 { 40 if(val[i^1] && dis[to[i]]>dis[x]-cos[i]) 41 { 42 dis[to[i]]=dis[x]-cos[i]; 43 if(!vis[to[i]]) q[++r]=to[i],vis[to[i]]=1; 44 } 45 } 46 vis[x]=0; 47 } 48 return dis[s]<inf; 49 } 50 int dfs(int x,int a) 51 { 52 if(x==t){vis[t]=1;return a;} 53 int res=0,f;vis[x]=1; 54 for(int i=fst[x];i!=-1;i=nxt[i]) 55 if(!vis[to[i]]&&val[i]&&dis[x]-cos[i]==dis[to[i]]) 56 { 57 f=dfs(to[i],min(val[i],a-res)); 58 if(f)ans+=f*cos[i],val[i]-=f,val[i^1]+=f,res+=f; 59 if(res==a)break; 60 } 61 return res; 62 } 63 void solve() 64 { 65 int f=0; 66 while(spfa()) 67 { 68 vis[t]=1; 69 while(vis[t]) 70 { 71 memset(vis,0,sizeof(vis)); 72 f+=dfs(s,2139062143); 73 } 74 } 75 printf("%d %lld\n",f,-ans); 76 } 77 }Z; 78 int main() 79 { 80 int g,h; 81 while(cin>>n>>m) 82 { 83 if(!n&&!m) return 0; 84 Z.mem(); 85 s=0,t=n+m+1; 86 for(int i=1;i<=n;i++) {a[i]=read();Z.add(s,i,1,-a[i]);Z.add(i,s,0,a[i]);} 87 for(int j=1;j<=m;j++) 88 { 89 g=read(),h=read(); 90 for(int i=1;i<=n;i++) 91 if(h>=a[i]) {Z.add(i,n+j,1,0);Z.add(n+j,i,0,0);} 92 Z.add(n+j,t,g,0);Z.add(t,n+j,0,0); 93 } 94 Z.solve(); 95 } 96 }
棒神写的费用流没T 还是我太弱了 %%%棒神
然后发现有个贪心就是使每个球尽可能价值最大,A了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define ll long long 11 #define inf 2139062143 12 #define MAXN 220 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); 19 return x*f; 20 } 21 int n,m,a[MAXN]; 22 struct data 23 { 24 int q,c; 25 bool operator < (const data &x)const 26 { 27 return q<x.q||(q==x.q&&c<x.c); 28 } 29 }b[MAXN]; 30 int main() 31 { 32 int ans,res,j; 33 while(scanf("%d%d",&n,&m)!=EOF&&n&&m) 34 { 35 ans=res=0; 36 for(int i=1;i<=n;i++) a[i]=read(); 37 for(int i=1;i<=m;i++) b[i].c=read(),b[i].q=read(); 38 sort(a+1,a+n+1); 39 sort(b+1,b+m+1); 40 j=m; 41 for(int i=n;i&&j;i--) 42 { 43 while(!b[j].c) j--; 44 if(b[j].q>=a[i]) b[j].c--,ans++,res+=a[i]; 45 } 46 printf("%d %d\n",ans,res); 47 } 48 }