Codeforces Round #185 (Div. 1) E.Biologist 最小割最大流
来源:互联网 发布:域名购买后续费 编辑:程序博客网 时间:2024/05/16 17:53
题目地址:http://codeforces.com/problemset/problem/311/E
思想上有些近似于最大闭权合图,详细参考《最小割模型在信息学竞赛中的应用》。
建图:
对于每只dog , 如果它的性别为0,建s->dog ,容量为cost,表示对它变性需要的费用。
反之性别为1,建dog->t,容量为cost,同样表示对他变性需要的费用。
对于每个folk:
(1)如果他要求的性别为0,建s->folk ,容量为赞助费,表示如果没能满足他损失的钱。
(如果是friend,容量为赞助费+道歉费)
对于他的每只dog,建folk->dog,容量为无穷大。
(2)反之他要求的性别为1,建folk->t,容量与之前一样。
对于他的每只dog,建dog->folk,容量为无穷大。
最后用所有的赞助费-最大流就好了。
这样建图,对于每只dog,他在变性的同时手术费和赞助费就绑定在一起的,在进行手术的同时赞助费和手术费就一起扣掉了。
如果在损失掉一部分赞助费和手术费的同时能得到另一笔赞助费,取损失最小的,由此构成了最小割。
如果还不懂的建议先把论文里的最大闭权合图弄懂。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cstdlib>#include <queue>#include <stack>#include <utility>#include <set>#include <map>#include <cmath>using namespace std;#define REP(i,n) for(int i=0;i<(n);++i)#define FOR(i,l,r) for(int i=(l);i<=(r);++i)#define DWN(i,r,l) for(int i=(r);i>=(l);--i)#define pb push_back#define mp(a,b) make_pair(a,b)#define INF 1e9#define N 15000#define M 3000000int head[N],ip;struct Edge{ int to,next,c;}edge[M];void add(int u,int v,int c){ edge[ip].to=v;edge[ip].c=c;edge[ip].next=head[u];head[u]=ip++; edge[ip].to=u;edge[ip].c=0;edge[ip].next=head[v];head[v]=ip++;}int level[N],que[N];bool makelevel(int s,int t){ memset(level,0,sizeof(level)); int iq=0,top,to,c; que[iq++]=s; level[s]=1; REP(i,iq) { top=que[i]; if(top==t) return 1; for(int p=head[top];p!=-1;p=edge[p].next) { to=edge[p].to,c=edge[p].c; if(!level[to] && c>0) { que[iq++]=to; level[to]=level[top]+1; } } } return 0;}int dfs(int pos,int maxf,int end){ if(pos==end) return maxf; int ret=0,to,c,temp; for(int p=head[pos];p!=-1;p=edge[p].next) { to=edge[p].to,c=edge[p].c; if(c>0 && level[to]==level[pos]+1 ) { temp=dfs(to,min(maxf-ret,c),end); edge[p].c-=temp; edge[p^1].c+=temp; ret+=temp; if(ret==maxf) return ret; } } --level[pos]; return ret;}int dinic(int start,int end){ int ret=0; while(makelevel(start,end)) ret+=dfs(start,INF,end); return ret;}int sex[N];int main(){ int n,m,g,x; while(cin>>n>>m>>g) { memset(head,-1,sizeof(head)); ip=0; int start=0,end=n+m+1; FOR(i,1,n) scanf("%d",&sex[i]); FOR(i,1,n) { scanf("%d",&x); if(sex[i]==0) add(start,i,x);//性别为0,建s->dog else add(i,end,x); //性别为1,建dog->t } int ans=0; FOR(i,n+1,n+m) { int p,pay,num,flag; scanf("%d%d%d",&p,&pay,&num); ans+=pay;//先加上所有的赞助费,最后用所有的赞助费减掉最小损失 while(num--) { scanf("%d",&x); if(p==0) add(i,x,INF); //要求的性别为0,每只dog,建folk->dog else add(x,i,INF); //要求的性别为1,每只dog,建dog->folk } scanf("%d",&flag); if(flag) pay+=g; if(p==0) add(start,i,pay);//要求的性别为0,建s->folk else add(i,end,pay); //要求的性别为1,建folk->t } cout<<ans-dinic(start,end)<<endl; } return 0;}
- Codeforces Round #185 (Div. 1) E.Biologist 最小割最大流
- Codeforces 311E. Biologist (最小割)
- 【Codeforces Round #185】Codeforces 311E Biologist
- [Codeforces311E]Biologist 最小割
- Codeforces 724E 最大流=最小割+dp求最小割
- CodeForces 311E Biologist
- 【CodeForces】311E Biologist
- DP+最小割——Intel Code Challenge Final Round (div.1 + div.2 combined) E
- [Codeforces Round #325][Div.1 E]
- Codeforces Round #347 (Div. 1) E
- Codeforces Round #323 (Div. 1) E
- Codeforces Round #200 Div.1 E tree
- Codeforces Round #147 (Div. 2) E Build String(最小费用流)
- Codeforces Round #290 (Div. 2) E. Fox And Dinner 网络流 最大流
- Codeforces Round #290 (Div. 2)E. Fox And Dinner——最大流 奇偶建图
- Codeforces Round #304 (Div. 2) E - Soldier and Traveling 最大流 isap
- Codeforces Round #304 (Div. 2) E. Soldier and Traveling 最大流 Dinic EK 算法
- Codeforces Round #304 (Div. 2) 546 E - Soldier and Traveling 最大流
- Ubuntu文本编辑器的乱码问题
- java HttpConnection的post和get传参
- 配置eclipse开发ssh框架(二)
- sqlserver 链接服务器 用远程表更新本地数据表失败
- 实现ListView的item逐个飞入效果——LayoutAnimationController
- Codeforces Round #185 (Div. 1) E.Biologist 最小割最大流
- ASP.net 路径问题 详解
- [搜狐笔试]显示所有正确的括号匹配
- unix/linux下线程私有数据实现原理及使用方法
- 常用排序方法(一)
- 为什么eclipse中加了adt插件后eclipse中没有显示ADT和SDK图标
- GetSystemTime和GetLocalTime的区别
- httputil
- 工作 & 梦想