[CODEVS1907]方格取数3(最小割)

来源:互联网 发布:超级数据恢复软件破解 编辑:程序博客网 时间:2024/05/18 00:37

题目:

我是超链接

题解:

将棋盘进行黑白染色,黑色和黑色可以一起涂。建立源点和汇点,源点连黑点容量为黑点值,汇点连白点容量为白点值,其他如果黑白点相邻,则连容量为INF的边

其实就是求最小割(最大流),只要源点和汇点不再相连,黑格和白格就不会相连

对于这道题,割掉了就不选了嘛

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <queue>#define INF 1e9#define N 2000using namespace std;int m,n,cap;int next[N*4+5],point[N*4+5],v[N*4+5],remind[N*4+5],deep[N*4+5],num[N*4+5],last[N*4+5],tot=-1,maxflow=0,cur[N*4+5];void addline(int x,int y,int cap){++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remind[tot]=cap;++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remind[tot]=0;}void bfs(int t){queue<int>q;for (int i=1;i<=t;i++) deep[i]=t;deep[t]=0;q.push(t);while (!q.empty()){int x=q.front(); q.pop();for (int i=point[x];i!=-1;i=next[i])  if (remind[i^1]&&deep[v[i]]==t)  {  deep[v[i]]=deep[x]+1;  q.push(v[i]);  }}}int addflow(int s,int t){int now=t,ans=INF;while (now!=s){ans=min(ans,remind[last[now]]);now=v[last[now]^1];}now=t;while (now!=s){remind[last[now]]-=ans;remind[last[now]^1]+=ans;now=v[last[now]^1];}return ans;}void isap(int s,int t){bfs(t);int now=s,i;for (i=s;i<=t;i++) ++num[deep[i]]; for (i=s;i<=t;i++) cur[i]=point[i];while (deep[s]<t){if (now==t){maxflow+=addflow(s,t);now=s;}bool has_find=false;for (int i=cur[now];i!=-1;i=next[i])  if (remind[i] && deep[v[i]]+1==deep[now])  {  last[v[i]]=i;  cur[now]=i;  now=v[i];  has_find=true;  break;  }if (!has_find){int minn=t-1;for (int i=point[now];i!=-1;i=next[i])  if (remind[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];  }}}int main(){int a,b,cap,sum=0,loc,loc1;memset(next,-1,sizeof(next));memset(point,-1,sizeof(point));scanf("%d%d",&m,&n); for (int i=1;i<=m;i++)  for (int j=1;j<=n;j++)  {  scanf("%d",&cap);  sum+=cap;  loc=(i-1)*n+j;  if (i%2==0)//偶数排   {  if (j%2==0) //偶数个为黑点   {  addline(0,loc,cap);if (i>1){loc1=(i-2)*n+j;addline(loc,loc1,INF);}if (i<m){loc1=loc+n;addline(loc,loc1,INF);}if (j>1){loc1=loc-1;addline(loc,loc1,INF);} if (j<n){loc1=loc+1;addline(loc,loc1,INF);}}  else  addline(loc,n*m+1,cap);}else//奇数排 {if (j%2==0)//偶数个   addline(loc,n*m+1,cap);else//奇数个为黑点 {addline(0,loc,cap);if (i>1){loc1=(i-2)*n+j;addline(loc,loc1,INF);}if (i<m){loc1=loc+n;addline(loc,loc1,INF);}if (j>1){loc1=loc-1;addline(loc,loc1,INF);} if (j<n){loc1=loc+1;addline(loc,loc1,INF);}}}  }isap(0,n*m+1);printf("%d",sum-maxflow);}


0 0