BZOJ2132
2016-03-20 09:26
351 查看
思路:
首先这道题目和同桌的你很像。可以说是一类经典问题。如果两个相邻的格子相同有收益。那么很明显的最小割建模。不同的话就将格子黑白染色成为二分图。白点连边不变。黑点到S,T的连边swap这样就可以转化成相同有收益的模型了。
首先这道题目和同桌的你很像。可以说是一类经典问题。如果两个相邻的格子相同有收益。那么很明显的最小割建模。不同的话就将格子黑白染色成为二分图。白点连边不变。黑点到S,T的连边swap这样就可以转化成相同有收益的模型了。
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<queue> #include<vector> using namespace std; const int imax=100+9; const int dmax=10000+229; const int bmax=200000+229; const int inf=100000229; const int dx[4]={0,0,1,-1}; const int dy[4]={1,-1,0,0}; int n,m,a[imax][imax],c[imax][imax],sum; int S,T,num,head[dmax],to[bmax],inext[bmax],re[bmax]; void iadd(int u,int v,int flow){ to[num]=v; re[num]=flow; inext[num]=head[u]; head[u]=num++; } void add(int u,int v,int flow){ iadd(u,v,flow); iadd(v,u,0);} void iread() { scanf("%d%d",&n,&m); S=0; T=n*m+1; int tot=0; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=++tot; //A for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int v; scanf("%d",&v); sum+=v; if((i+j)&1) add(S,a[i][j],v); else add(a[i][j],T,v); } //B for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int v; scanf("%d",&v); sum+=v; if((i+j)&1) add(a[i][j],T,v); else add(S,a[i][j],v); } //C for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&c[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int val; if((i+j)&1) { int u=a[i][j]; for(int k=0;k<4;k++) { int nowx=i+dx[k]; int nowy=j+dy[k]; int v=a[nowx][nowy]; if(!v) continue; int nowv=c[i][j]+c[nowx][nowy]; add(u,v,nowv); add(v,u,nowv); sum+=nowv; } } } } queue<int> q; bool vis[dmax]; int d[dmax]; bool BFS() { memset(d,0,sizeof(d)); vis[S]=1; q.push(S); d[S]=1; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=inext[i]) if(re[i] && !d[to[i]]) { d[to[i]]=d[u]+1; if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1; } } return d[T]!=0; } int DFS(int x,int c) { if(x==T || c==0) return c; int r=c; for(int i=head[x];i!=-1;i=inext[i]) if(re[i] && d[to[i]]==d[x]+1) { int f=DFS(to[i],min(re[i],r)); r-=f; re[i]-=f; re[i^1]+=f; if(!r) break; } if(r==c) d[x]=0; return c-r; } void iwork() { int ans=0; while(BFS()) ans+=DFS(S,inf); printf("%d\n",sum-ans); } int main() { iread(); iwork(); return 0; }
相关文章推荐
- Poj2638 网络流+最短路+二分答案
- BZOJ3275 Number (最小割)
- [笔记] 网络流-最大流 POJ-1273\HDU-4240
- 上下界网络流初探
- Edmonds-Karp 最大流 hdu 1532 Drained Ditches
- 网络流_poj1273
- POJ 1273 Drainage Ditches 最大流 dinic
- POJ1273-Drainage Ditches
- 【网络流】复杂的大门
- ACM/ICPC World Finals 2013 C Surely You Congest
- 网络流算法整理
- [BZOJ1797][AHOI2009][最大流][强连通分量]Mincut最小割
- [BZOJ2324][ZJOI2011][最小费用最大流]营救皮卡丘
- [BZOJ1834][ZJOI2010][最大流][最小费用最大流]网络扩容
- Topcoder SRM642 TaroCutting
- POJ2391解题报告
- uva 11248
- 【学习】网络流
- 【网络流之最小割模型】poj3469 BZOJ3144 UVA1212
- [网络流24题 #2]太空飞行计划问题