codevs 1907 方格取数 网络流
2017-07-03 21:39
267 查看
感觉自己宛如一个傻逼。
1907 方格取数 3
时间限制: 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
这是一道二分图带权最大独立集的题。
二分图带权最大独立集=权值和-最小点权覆盖
关于二分图带权最大独立集:
在二分图中,每个点都有一个权值,在保证两个点不相交的前提下,使所选的点权值和最大。
方法:
建一个源点s,s向二分图的左边的点(就这么说吧23333)连一条流量为点权的有向边,二分图的左边的点再向右边连一条流量为INF的边,然后右边所有点向汇点t连一条流量为该点权值的边。
最后的结果:所有点的权值和-最小割
同时这也是一道经典建模的题。
对于一个点(i,j) i+j为奇数的点肯定不与同为奇数的点有边相交,所以可以讨论i+j的奇偶将这堆点分为两部分。
可以令源点与i+j为奇的点相连,这些点再与与它有边相交的点相连,最后连向汇点就可。
代码:
1907 方格取数 3
时间限制: 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
这是一道二分图带权最大独立集的题。
二分图带权最大独立集=权值和-最小点权覆盖
关于二分图带权最大独立集:
在二分图中,每个点都有一个权值,在保证两个点不相交的前提下,使所选的点权值和最大。
方法:
建一个源点s,s向二分图的左边的点(就这么说吧23333)连一条流量为点权的有向边,二分图的左边的点再向右边连一条流量为INF的边,然后右边所有点向汇点t连一条流量为该点权值的边。
最后的结果:所有点的权值和-最小割
同时这也是一道经典建模的题。
对于一个点(i,j) i+j为奇数的点肯定不与同为奇数的点有边相交,所以可以讨论i+j的奇偶将这堆点分为两部分。
可以令源点与i+j为奇的点相连,这些点再与与它有边相交的点相连,最后连向汇点就可。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100010; const int INF = 0x73f3f3f; const int M = 35; struct node{ int pre,v,f; }edge ; int n,m; int head ; int a[M][M]; int num=1; void addedge(int from,int to,int f){ num++; edge[num].pre=head[from]; edge[num].v=to; edge[num].f=f; head[from]=num; num++; edge[num].pre=head[to]; edge[num].v=from; edge[num].f=0; head[to]=num; } int mmax=0; int s,t; int state ,dis ; bool vis ; bool bfs(){ int h=0,tail=1; state[1]=s,vis[s]=true,dis[s]=0; do{ h++; int u=state[h]; for(int i=head[u];i;i=edge[i].pre){ int v=edge[i].v; if(!vis[v]&&edge[i].f){ vis[v]=true; tail++; state[tail]=v; dis[v]=dis[u]+1; } } }while(h<tail); if(vis[t]) return true; return false; } inline int Min(int a,int b){ return a<b?a:b; } int dfs(int u,int delta){ if(u==t||delta==0) return delta; int ans=0; for(int i=head[u];i&δi=edge[i].pre){ int v=edge[i].v; if(dis[v]==dis[u]+1&&edge[i].f){ int dd=dfs(v,Min(edge[i].f,delta)); ans+=dd; delta-=dd; edge[i].f-=dd; edge[i^1].f+=dd; } } if(!ans) dis[u]=-1; return ans; } #define ms(x,y) memset(x,y,sizeof(x)) void zero(){ ms(state,0);ms(vis,0);ms(dis,0); } int maxflow(){ int ans=0; while(1){ zero(); if(!bfs()) break; ans+=dfs(s,INF); } return ans; } int main(){ scanf("%d%d",&n,&m); s=0,t=n*m+1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); mmax+=a[i][j]; int u=(i-1)*m+j; if((i+j)&1){ addedge(s,u,a[i][j]); if(j>1) addedge(u,u-1,INF); if(i>1) addedge(u,m*(i-2)+j,INF); if(j<m) addedge(u,u+1,INF); if(i<n) addedge(u,m*i+j,INF); } else addedge(u,t,a[i][j]); } } /*for(int i=head[4];i;i=edge[i].pre){ printf("%d %d\n",edge[i].v,edge[i].f); }*/ printf("%d ",mmax-maxflow()); return 0; }
相关文章推荐
- codevs1907 方格取数 3||tyvj1338QQ农场|网络流
- 【codevs1907】[网络流24题]方格取数3
- codevs 1907:方格取数3
- Codevs 1907 方格取数 3 最小割
- [codevs1907]方格取数3 最小割
- 【codevs1907】方格取数3 最大点权独立集
- CodeVS 1907 方格取数 3 (ISAP)
- CODEVS 1907 方格取数 3
- Codevs_P1227 方格取数2(拆点网络流+最小费用流)
- 【codevs1907】 方格取数 3
- 【codevs1907】方格取数3(最大流最小割定理)
- CodeVS1907 方格取数3
- 【Codevs1907】方格取数3(最小割)
- codevs1907方格取数最大流
- codevs1907 方格取数 3
- codevs 1227 方格取数 2 【网络流+费用流基础】
- 【codevs1907】【方格取数3】二分图最大带权独立集
- [CODEVS1907]方格取数3(最小割)
- codevs1034(网络流)
- 【codevs1922】[网络流24题]骑士共存问题