Codeforces 311E. Biologist (最小割)
来源:互联网 发布:中国的未来 知乎 编辑:程序博客网 时间:2024/06/06 01:29
题目描述
传送门
题目大意:有n个已经有初值的0/1变量,改变一个变量需要vi的花
费。有m个需求,要求某个集合的变量均为0/1,满足需
求得到wi的收益,对于某些集合不满足时需要付出额外的代价g。求最大收益。
题解
最小割。
与源点S相连表示选择的值为0,与汇点T相连表示选择的值为1.
S->
对于第i个需求建立点
如果该需求要求变量的值为0,那么
S->
如果该需求要求变量的值为1,那么
然后跑最大流求最小割flow。
最后的答案就是
代码
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#define N 500000#define inf 100000000using namespace std;int point[N],nxt[N],v[N],remain[N],tot,a[N],val[N];int last[N],deep[N],num[N],cur[N],n,m,g;void add(int x,int y,int z){ tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z; tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; //cout<<x<<" "<<y<<" "<<z<<endl;}int addflow(int s,int t){ int ans=inf; int now=t; while (now!=s) { ans=min(ans,remain[last[now]]); now=v[last[now]^1]; } now=t; while (now!=s) { remain[last[now]]-=ans; remain[last[now]^1]+=ans; now=v[last[now]^1]; } return ans;}void bfs(int s,int t){ for (int i=1;i<=t;i++) deep[i]=t; queue<int> p; p.push(t); deep[t]=0; while (!p.empty()){ int now=p.front(); p.pop(); for (int i=point[now];i!=-1;i=nxt[i]) if (deep[v[i]]==t&&remain[i^1]){ deep[v[i]]=deep[now]+1; p.push(v[i]); } }}int isap(int s,int t){ int ans=0; int now=s; bfs(s,t); for (int i=1;i<=t;i++) num[deep[i]]++; for (int i=1;i<=t;i++) cur[i]=point[i]; while (deep[s]<t) { if (now==t) { ans+=addflow(s,t); now=s; } bool pd=false; for (int i=point[now];i!=-1;i=nxt[i]) if (deep[v[i]]+1==deep[now]&&remain[i]){ pd=true; cur[now]=i; last[v[i]]=i; now=v[i]; break; } if (!pd) { int minn=t+1; for (int i=point[now];i!=-1;i=nxt[i]) if (remain[i]) minn=min(minn,deep[v[i]]); if (!--num[deep[now]]) break; num[deep[now]=minn+1]++; cur[now]=point[now]; if (now!=s) now=v[last[now]^1]; } } return ans;}int main(){ freopen("a.in","r",stdin); scanf("%d%d%d",&n,&m,&g); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++) scanf("%d",&val[i]); int S=n+m+1; int T=S+1; int sum=0; tot=-1; memset(point,-1,sizeof(point)); for (int i=1;i<=n;i++) if (a[i]) add(i,T,val[i]); else add(S,i,val[i]); for (int i=1;i<=m;i++) { int opt,w,k; scanf("%d%d%d",&opt,&w,&k); sum+=w; for (int j=1;j<=k;j++){ int x; scanf("%d",&x); if (opt) add(x,i+n,inf); else add(i+n,x,inf); } int mark; scanf("%d",&mark); if (mark) w+=g; if (opt) add(i+n,T,w); else add(S,i+n,w); } //cout<<sum<<endl; printf("%d\n",sum-isap(S,T));}
阅读全文
0 0
- Codeforces 311E. Biologist (最小割)
- CodeForces 311E Biologist
- 【CodeForces】311E Biologist
- Codeforces Round #185 (Div. 1) E.Biologist 最小割最大流
- [Codeforces311E]Biologist 最小割
- 【Codeforces Round #185】Codeforces 311E Biologist
- CodeForces 724E(Goods transportation 最小割)
- Codeforces 724E 最大流=最小割+dp求最小割
- Codefores #185E (div1) Biologist
- 【CF 724E】Goods transportation(最小割+DP)
- Atcoder KUPC2016 E柵 / Fences 最小割
- (最小割模板)
- bzoj1412(最小割)
- 日程表(最小割)
- poj3469(最小割)
- Codeforces--237E--Build String(最小费用流)
- Codeforces 240E Road Repairs(最小树形图路径)
- poj 1815(最小割、割集)
- Python中Unicode字符串
- Hibernate与 MyBatis的比较
- 局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍
- JSONP跨域请求原理及实现
- 03.20 Linux软硬链接区别
- Codeforces 311E. Biologist (最小割)
- 求解有向图的强联通分量的Java实现
- 关于Batch Normalization(批归一化)的理解
- Codevs2102[石子归并 2] 区间DP
- POJ
- ARP:地址解析协议
- 函数模板与类模板
- HTTP 状态码
- 32位下CPU的寻址方式