[BZOJ2127]happiness(网络流)
来源:互联网 发布:软件升级服务合同 编辑:程序博客网 时间:2024/06/03 18:47
=== ===
这里放传送门
=== ===
题解
非常经典的最小割建图模型啦!考虑最小的放弃的喜悦值,以S代表学文,T代表学理为例,首先对于单个同学来说,他的学文的喜悦值和学理的喜悦值不能同时存在,于是给每个同学建立一个点,从S连到它,流量为它学文的喜悦值;从它连到T,流量为它学理的喜悦值,那么这两条边必定要割掉一条。对于处理两个同学共同学文或者学理的情况,对每一对相邻的同学新建两个点,从S连到其中一个点,这个点再连到那两个同学,流量为这两个同学共同学文的喜悦值;这两个同学连到另外一个点,从这个点再连到T,流量为这两个同学共同学理的喜悦值。
搞出来就大概长这样,妈呀这图画起来真费事= =
代码
#include<cstdio>#include<cstring>#include<algorithm>#define inc(x)(x=(x%60000)+1)#define inf 1000000000using namespace std;int n,m,p[60010],tot,S,T,N,cnt,cur[60010],gap[60010],d[60010],pre[60010],sum;struct edge{ int to,flw,nxt;}e[3000010];int cal(int i,int j){ return (i-1)*m+j;}void add(int from,int to,int flow){ e[tot].to=to; e[tot].flw=flow; e[tot].nxt=p[from]; p[from]=tot; ++tot;}void Bfs(int N){ int q[60010],head,tail; for (int i=0;i<=N;i++) d[i]=N+1; memset(q,0,sizeof(q)); head=0;tail=1; q[tail]=T; d[T]=0; while (head!=tail){ int u; inc(head); u=q[head]; for (int i=p[u];i!=-1;i=e[i].nxt){ int v=e[i].to; if ((e[i^1].flw>0)&&(d[v]==N+1)){ d[v]=d[u]+1; inc(tail);q[tail]=v; } } }}int track(){ int Min=inf; for (int i=T;i!=S;i=e[pre[i]^1].to) Min=min(Min,e[pre[i]].flw); for (int i=T;i!=S;i=e[pre[i]^1].to){ e[pre[i]].flw-=Min; e[pre[i]^1].flw+=Min; } return Min;}int ISAP(int N){ int u=S,Flow=0; bool flag=false; Bfs(N); for (int i=0;i<=N;i++) cur[i]=p[i]; memset(gap,0,sizeof(gap)); memset(pre,0,sizeof(pre)); for (int i=0;i<=N;i++) ++gap[d[i]]; while (d[S]<N){ if (u==T){ Flow+=track(); u=S; } flag=false; for (int i=cur[u];i!=-1;i=e[i].nxt){ int v=e[i].to; if ((e[i].flw>0)&&(d[v]+1==d[u])){ flag=true; pre[v]=i; cur[u]=i;//更新当前弧 u=v; break; } } if (flag==false){ int v=N-1; for (int i=p[u];i!=-1;i=e[i].nxt) if (e[i].flw>0) v=min(v,d[e[i].to]); --gap[d[u]]; if (gap[d[u]]==0) break; d[u]=v+1; ++gap[d[u]]; cur[u]=p[u];//初始化这个点对应的当前弧 if (u!=S) u=e[pre[u]^1].to; } } return Flow;}int main(){ memset(p,-1,sizeof(p)); scanf("%d%d",&n,&m); N=n*m;tot=cnt=0; S=0;T=N*5+1; sum=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ int x; ++cnt; scanf("%d",&x); sum+=x;//计算总的喜悦值 add(S,cnt,x);add(cnt,S,0);//建立每个同学对于学文的喜悦值 } cnt=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ int x; ++cnt; scanf("%d",&x); sum+=x; add(cnt,T,x);add(T,cnt,0);//建立每个同学对于学理的喜悦值 } for (int i=1;i<n;i++) for (int j=1;j<=m;j++){ int x,pt; cnt=cal(i,j); pt=cnt+N;//计算第一组点的编号 scanf("%d",&x); sum+=x; add(S,pt,x);add(pt,S,0); add(pt,cnt,x);add(cnt,pt,0); add(pt,cnt+m,x);add(cnt+m,pt,0); } for (int i=1;i<n;i++) for (int j=1;j<=m;j++){ int x,pt; cnt=cal(i,j); pt=cnt+2*N; scanf("%d",&x); sum+=x; add(pt,T,x);add(T,pt,0); add(cnt,pt,x);add(pt,cnt,0); add(cnt+m,pt,x);add(pt,cnt+m,0); } for (int i=1;i<=n;i++) for (int j=1;j<m;j++){ int x,pt; cnt=cal(i,j); pt=cnt+3*N; scanf("%d",&x); sum+=x; add(S,pt,x);add(pt,S,0); add(pt,cnt,x);add(cnt,pt,0); add(pt,cnt+1,x);add(cnt+1,pt,0); } for (int i=1;i<=n;i++) for (int j=1;j<m;j++){ int x,pt; cnt=cal(i,j); pt=cnt+4*N; scanf("%d",&x); sum+=x; add(pt,T,x);add(T,pt,0); add(cnt,pt,x);add(pt,cnt,0); add(cnt+1,pt,x);add(pt,cnt+1,0); } printf("%d\n",sum-ISAP(T)); return 0;}
偏偏在最后出现的补充说明
做最小割这样的题的时候一定要分清楚建图是关于舍弃的价值还是得到的价值,愚蠢的ATP好几次都把这两个像和稀泥一样混到一起然后图就建成了一坨shi怎么也跑不动= =
0 0
- [BZOJ2127]happiness(网络流)
- 【BZOJ2127】happiness 网络流
- 【BZOJ2127】happiness(网络流dinic)
- bzoj2127 happiness(最小割)
- bzoj2127 happiness
- bzoj2127: happiness
- bzoj2127 happiness
- BZOJ2127: happiness
- bzoj2127 happiness
- 【bzoj2127】happiness
- bzoj2127 happiness
- bzoj2127 happiness
- bzoj2127: happiness 最小割
- 【bzoj2127】happiness 最小割
- bzoj2127 happiness 最小割
- BZOJ2127 happiness-最小割
- [bzoj2127] happiness 最小割
- [JZOJ1919] [BZOJ2127]【2011集训队出题】happiness(最小割之二元关系)
- 浅析人脸检测之Haar分类器方法:Haar特征、积分图、 AdaBoost 、级联
- Java数据结构-Hashmap
- 部署ArcGIS JS API 离线包(Tomcat与IIS)
- JavaScript
- 《笨办法学python》笔记(完结)
- [BZOJ2127]happiness(网络流)
- 【BZOJ 1002】 [FJOI2007]轮状病毒 【矩阵树定理】【留坑】
- 20161102
- TCP拥塞控制算法-从BIC到CUBIC
- MVC三层架构
- Java中集合List按照集合内实体类元素的指定字段排序方法
- 程序员应该知道的 关于const和static
- 基本标示符-宏-编译连接
- 在云服务器上搭建git服务器遇到的问题及解决