[BZOJ2132]圈地计划(最小割)
2016-04-07 19:17
393 查看
题目描述
传送门题解
抄黄学长的题解。黑白染色,对于每个黑点A,S->A:W商业,A->T:W工业,对于每个白点B,S->B:W工业,B->T:W商业,对于每对有关系的两点A,B,A<–>B:c1+c2。
这个建模感受一下就是对的。
看黄学长的姿势之后发现中间那两条边没加反向边,但是据ATP说加了也没错,只是慢了一点。
应该就是两边都能流叭
代码
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int max_n=105; const int max_m=105; const int max_N=max_n*max_m+2; const int max_M=max_N*10; const int max_e=max_M; const int INF=1e9; int n,m,N,now,cnt,sum,maxflow; int now1,now2,now3,now4; int a[max_n][max_m],b[max_n][max_m],c[max_n][max_m],color[max_n][max_m]; int tot,point[max_N],next[max_e],v[max_e],remain[max_e]; int deep[max_N],cur[max_N]; queue <int> q; inline void add(int x,int y,int cap){ ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap; } inline void addedge(int x,int y,int cap){ sum+=cap; add(x,y,cap); add(y,x,0); } inline bool bfs(int s,int t){ memset(deep,0x7f,sizeof(deep)); deep[s]=0; for (int i=1;i<=N;++i) cur[i]=point[i]; while (!q.empty()) q.pop(); q.push(s); while (!q.empty()){ int now=q.front(); q.pop(); for (int i=point[now];i!=-1;i=next[i]) if (deep[v[i]]>INF&&remain[i]){ deep[v[i]]=deep[now]+1; q.push(v[i]); } } return deep[t]<INF; } inline int dfs(int now,int t,int limit){ if (now==t||!limit) return limit; int flow=0,f; for (int i=cur[now];i!=-1;i=next[i]){ cur[now]=i; if (deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(remain[i],limit)))){ flow+=f; limit-=f; remain[i]-=f; remain[i^1]+=f; if (!limit) break; } } return flow; } inline void dinic(int s,int t){ while (bfs(s,t)) maxflow+=dfs(s,t,INF); } int main(){ tot=-1; memset(point,-1,sizeof(point)); memset(next,-1,sizeof(next)); scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) scanf("%d",&a[i][j]); for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) scanf("%d",&b[i][j]); for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) scanf("%d",&c[i][j]); N=n*m+2; for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) if (i%2){ if (j%2) color[i][j]=1; else color[i][j]=0; } else{ if (j%2) color[i][j]=0; else color[i][j]=1; } for (int i=1;i<=n;++i) for (int j=1;j<=m;++j){ now=(i-1)*m+j; if (color[i][j]==1){ addedge(1,1+now,a[i][j]); addedge(1+now,N,b[i][j]); } else{ addedge(1,1+now,b[i][j]); addedge(1+now,N,a[i][j]); } if (!color[i][j]) continue; if (i!=1) now1=now-m,add(1+now,1+now1,c[i][j]+c[i-1][j]),add(1+now1,1+now,c[i][j]+c[i-1][j]),sum+=c[i][j]+c[i-1][j]; if (i!=n) now2=now+m,add(1+now,1+now2,c[i][j]+c[i+1][j]),add(1+now2,1+now,c[i][j]+c[i+1][j]),sum+=c[i][j]+c[i+1][j]; if (j!=1) now3=now-1,add(1+now,1+now3,c[i][j]+c[i][j-1]),add(1+now3,1+now,c[i][j]+c[i][j-1]),sum+=c[i][j]+c[i][j-1]; if (j!=m) now4=now+1,add(1+now,1+now4,c[i][j]+c[i][j+1]),add(1+now4,1+now,c[i][j]+c[i][j+1]),sum+=c[i][j]+c[i][j+1]; } dinic(1,N); printf("%d\n",sum-maxflow); }
相关文章推荐
- apache跨域问题
- 脱离 Spring 实现复杂嵌套事务,之三(REQUIRES_NEW - 独立事务)
- 脱离 Spring 实现复杂嵌套事务,之四(NESTED - 嵌套事务)
- C++实现——由年月日推算是星期几
- C# 网络编程之基于SMTP发送电子邮件
- Android官方开发文档Training系列课程中文版:通过NFC共享文件之发送文件到另一台设备
- 剑指offer-面试题2.实例Singleton模式
- [UOJ35]后缀排序
- ssh 登录出现的几种错误以及解决办法
- 脱离 Spring 实现复杂嵌套事务,之二(REQUIRED - 加入已有事务)
- 链表--单链表
- 问卷
- does not match bootstrap parameter
- 4.8 团队分析
- 脱离 Spring 实现复杂嵌套事务,之一(必要的概念)
- JavaScript之流程控制
- MySQL性能优化的21个最佳实践 和 mysql使用索引
- 剑指offer面试题 圆圈中最后剩下的数字(约瑟夫环问题)
- 九度OJ1184二叉树
- 学习进度表