AC日记——[网络流24题]方格取数问题 cogs 734
2017-03-04 16:12
357 查看
734. [网络流24题] 方格取数问题
★★☆ 输入文件:grid.in输出文件:
grid.out简单对比
时间限制:1 s 内存限制:128 MB
«问题描述:
在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
«编程任务:
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
«数据输入:
由文件grid.in提供输入数据。文件第1 行有2 个正整数m和n,分别表示棋盘的行数
和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。
«结果输出:
程序运行结束时,将取数的最大总和输出到文件grid.out中。
输入文件示例 输出文件示例
grid.in
3 3
1 2 3
3 2 3
2 3 1
grid.out
11
(1<=N,M<=30)
思路:
取数;
取出的数满足任意两两坐标不相邻;
所以,我们把点标记;
把全部的点都用bfs标记成true或者false;
true与true不相邻,false与false不相邻;
然后标记为true的点在集合a;
标记为false的点在集合b;
建立超级源点s和超级汇点t;
s向a的每个点连边,流量为点的权值;
t向b的每个点连边,流量为点的权值;
然后,a中与b相邻的点连边,流量无限大;
然后求出最小割;
最后的ans等于所有点权值的总和减去最小割;
来,上代码:
#include <queue> #include <cstdio> #include <iostream> using namespace std; struct ColorNode { int x,y; bool color; }; struct EdgeType { int v,f,e; }; struct EdgeType edge[900000]; const int dx[5]={0,-1,0,1,0}; const int dy[5]={0,0,1,0,-1}; int n,m,dis[50][50],ans,head[1001],s=0,t; int cnt=1,deep[1001]; bool if_[50][50]; char Cget; inline void in(int &now) { now=0,Cget=getchar(); while(Cget>'9'||Cget<'0') Cget=getchar(); while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } } struct ColorNode node(int x,int y,int color) { struct ColorNode pos; pos.x=x,pos.y=y,pos.color=color; return pos; } inline void edge_add(int u,int v,int f) { edge[++cnt].v=v,edge[cnt].f=f,edge[cnt].e=head[u],head[u]=cnt; edge[++cnt].v=u,edge[cnt].f=0,edge[cnt].e=head[v],head[v]=cnt; } bool BFS() { queue<int>que; for(int i=s;i<=t;i++) deep[i]=-1; deep[s]=0;que.push(s); while(!que.empty()) { int pos=que.front();que.pop(); for(int i=head[pos];i;i=edge[i].e) { if(deep[edge[i].v]<0&&edge[i].f>0) { deep[edge[i].v]=deep[pos]+1; if(edge[i].v==t) return true; que.push(edge[i].v); } } } return false; } int flowing(int now,int flow) { if(now==t||flow<=0) return flow; int oldflow=0; for(int i=head[now];i;i=edge[i].e) { if(edge[i].f<=0||deep[edge[i].v]!=deep[now]+1) continue; int pos=flowing(edge[i].v,min(edge[i].f,flow)); flow-=pos; oldflow+=pos; edge[i].f-=pos; edge[i^1].f+=pos; if(flow==0) return oldflow; } return oldflow; } int main() { freopen("grid.in","r",stdin); freopen("grid.out","w",stdout); in(n),in(m);t=n*m+1; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { in(dis[i][j]); ans+=dis[i][j]; } } queue<ColorNode>que; if_[1][1]=true; que.push(node(1,1,if_[1][1])); while(!que.empty()) { struct ColorNode pos=que.front();que.pop(); if(pos.color) { edge_add(s,(pos.x-1)*m+pos.y,dis[pos.x][pos.y]); int x=pos.x,y=pos.y,hash=(pos.x-1)*m+pos.y; for(int i=1;i<=4;i++) { if(x+dx[i]>0&&x+dx[i]<=n&&y+dy[i]>0&&y+dy[i]<=m) { edge_add(hash,(pos.x+dx[i]-1)*m+pos.y+dy[i],0x7ffffff); } } } else edge_add((pos.x-1)*m+pos.y,t,dis[pos.x][pos.y]); if(pos.x+1<=n&&!if_[pos.x+1][pos.y]) { que.push(node(pos.x+1,pos.y,!pos.color)); if_[pos.x+1][pos.y]=true; } if(pos.y+1<=m&&!if_[pos.x][pos.y+1]) { if_[pos.x][pos.y+1]=true; que.push(node(pos.x,pos.y+1,!pos.color)); } } while(BFS()) ans-=flowing(s,0x7ffffff); cout<<ans; return 0; }
相关文章推荐
- [网络流24题] 方格取数问题(cogs 734)
- AC日记——[网络流24题]骑士共存 cogs 746
- COGS 734. [网络流24题] 方格取数问题
- Cogs 734. [网络流24题] 方格取数问题(最大闭合子图)
- cogs 734. [网络流24题] 方格取数问题
- 【网络流24题】【COGS14】飞行员搭配问题
- cogs 396. [网络流24题]魔术球问题(简化版
- cogs 740. [网络流24题] 分配问题
- [网络流24题] COGS 运输问题1
- 【费用流】【网络流24题】【cogs 739】运输问题
- [网络流24题] 方格取数问题 (最大点权独立集)
- 【网络流24题----09】方格取数问题
- [网络流24题] 方格取数问题 (最大权独立集---网络最小割)
- [网络流24题] COGS 运输问题1
- [网络流24题 #9]方格取数问题
- 【费用流】【网络流24题】【cogs 739】运输问题
- 【网络流24题】No.9 方格取数问题 (二分图点权最大独立集)
- 【网络流24题】方格取数问题
- [网络流24题-5] cogs739 运输问题
- Cogs 739. [网络流24题] 运输问题(费用流)