Codevs_P1907&HDU_P1565 方格取数3(最大流)
2016-01-03 14:57
295 查看
时间限制: 2 s
空间限制: 256000 KB
题目等级 : 大师 Master
题目描述 Description
问题描述:
在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
«编程任务:
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
输入描述 Input Description
第1 行有2 个正整数m和n,分别表示棋盘的行数
和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。
输出描述 Output Description
将取数的最大总和输出
样例输入 Sample Input
3 3
1 2 3
3 2 3
2 3 1
样例输出 Sample Output
11
数据范围及提示 Data Size & Hint
n,m<=30
思路:黑白染色,设置一个超级源点和汇点,源点连接所有黑点,白点连接汇点,流量都是该点的权值。将黑白点之间用流量为INF的边相连,做一遍最大流,得到所有必须的可行割,用总数减去它即为答案
空间限制: 256000 KB
题目等级 : 大师 Master
题目描述 Description
问题描述:
在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
«编程任务:
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
输入描述 Input Description
第1 行有2 个正整数m和n,分别表示棋盘的行数
和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。
输出描述 Output Description
将取数的最大总和输出
样例输入 Sample Input
3 3
1 2 3
3 2 3
2 3 1
样例输出 Sample Output
11
数据范围及提示 Data Size & Hint
n,m<=30
思路:黑白染色,设置一个超级源点和汇点,源点连接所有黑点,白点连接汇点,流量都是该点的权值。将黑白点之间用流量为INF的边相连,做一遍最大流,得到所有必须的可行割,用总数减去它即为答案
#include<cstdio> #include<climits> #include<cstring> #include<queue> #include<vector> #include<iostream> using namespace std; #define N 31 #define INF INT_MAX/3*2 struct Min_Cut{ struct Edge{ int fr,to,cap,flow; Edge(int f,int t,int c,int fl):fr(f),to(t),cap(c),flow(fl){} }; vector<Edge> edge;vector<int> g[N*N]; int n,m,flow,total,S,T;int p[N*N],a[N*N],w ; int hash(int x,int y){return (x-1)*n+y;} void Add_Edge(int fr,int to,int cap){ edge.push_back(Edge(fr,to,cap,0)); edge.push_back(Edge(to,fr,0,0)); int t=edge.size(); g[fr].push_back(t-2);g[to].push_back(t-1); return; } int in(){ int x=0;char ch=getchar(); while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } void clear(){ flow=0,total=0;memset(w,0,sizeof(w)); for(int i=0;i<N*N;i++) g[i].clear(); edge.clear();return; } void init(){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ w[i][j]=in(); total+=w[i][j]; } S=0,T=n*n+1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if((i+j)&1) Add_Edge(hash(i,j),T,w[i][j]); else{ Add_Edge(S,hash(i,j),w[i][j]); if(i>1) Add_Edge(hash(i,j),hash(i-1,j),INF); if(i<n) Add_Edge(hash(i,j),hash(i+1,j),INF); if(j>1) Add_Edge(hash(i,j),hash(i,j-1),INF); if(j<n) Add_Edge(hash(i,j),hash(i,j+1),INF); } } return; } int Max_Flow(int s,int t){ for(;;){ memset(a,0,sizeof(a)); queue<int> q; q.push(s);a[s]=INT_MAX; while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<g[x].size();i++){ Edge& e=edge[g[x][i]]; if(!a[e.to]&&e.cap>e.flow){ p[e.to]=g[x][i]; a[e.to]=min(a[x],e.cap-e.flow); q.push(e.to); } } if(a[t]) break; } if(!a[t]) break; for(int u=t;u!=s;u=edge[p[u]].fr){ edge[p[u]].flow+=a[t]; edge[p[u]^1].flow-=a[t]; } flow+=a[t]; } return flow; } void solve(){ while(scanf("%d",&n)!=EOF){ clear();init();Max_Flow(S,T); printf("%d\n",total-flow); } } }s; int main(){ s.solve(); return 0; }
相关文章推荐
- 卷积和相关
- iOS开发- reloadData无效 (子线程更新UI错误)
- 单例模式
- Java的Hibernate框架中用于操作数据库的HQL语句讲解
- Android Dagger2学习
- 2016 第2讲 Scala面向对象彻底精通及Spark源码阅读
- NodeJS会是昙花一现吗?
- c++ 读文件,fscanf结尾问题
- 06.创建型————原型模式
- HDU 1114 Piggy-Bank(完全背包)
- 上传几张智能开关产品图片
- bzoj 1602 [Usaco2008 Oct]牧场行走(LCA模板)
- letcode之Recover Binary Search Tree
- 顺序表一系列操作
- mokoid android open source HAL hacking in a picture
- [codeforces]Goodbye_2015
- .NET中类型转换的一些等价用法
- 精神粮食--有梦想的人可以看看
- MVC导出Excle
- 一个可以用于在百科搜索大量关键词的python爬虫