Round 6 F - 方格取数(2) HDU - 1569 网络流
2017-07-24 01:20
441 查看
网络流题
题目链接:
HDU 1569
方格取数(2)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6558 Accepted Submission(s): 2095
Problem Description
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
Input
包括多个测试实例,每个测试实例包括2整数m,n和m*n个非负数(m<=50,n<=50)
Output
对于每个测试实例,输出可能取得的最大的和
Sample Input
3 3
75 15 21
75 15 28
34 70 5
Sample Output
188
思路:
放在网络流专题里自然会想到网络流,联想到建虚拟源点、虚拟汇点来建图。
具体建图:
将棋盘黑白染色,白点连接虚拟源点,黑点连接虚拟汇点,费用为该点值,相邻不同颜色点也连接,费用为无限大。
从 S 到 T 跑一遍最小费用流。
因为相邻点里总会取走一个,所有用总和 sum 减去这个最小费用 , 就是最大值,且两两点不相邻。
可以拿来当模板:
题目链接:
HDU 1569
方格取数(2)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6558 Accepted Submission(s): 2095
Problem Description
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
Input
包括多个测试实例,每个测试实例包括2整数m,n和m*n个非负数(m<=50,n<=50)
Output
对于每个测试实例,输出可能取得的最大的和
Sample Input
3 3
75 15 21
75 15 28
34 70 5
Sample Output
188
思路:
放在网络流专题里自然会想到网络流,联想到建虚拟源点、虚拟汇点来建图。
具体建图:
将棋盘黑白染色,白点连接虚拟源点,黑点连接虚拟汇点,费用为该点值,相邻不同颜色点也连接,费用为无限大。
从 S 到 T 跑一遍最小费用流。
因为相邻点里总会取走一个,所有用总和 sum 减去这个最小费用 , 就是最大值,且两两点不相邻。
可以拿来当模板:
#include<iostream> #include<cstring> #include<string> #include<cmath> #include<vector> #include<cstdio> #include<queue> using namespace std; typedef long long ll; #define N 3000 #define mem(s,t) memset(s,t,sizeof(s)) #define inf 0x3f3f3f3f int E,V; struct Edge{ int from, to, cap,flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){ } }; struct Dinic{ int n,m,s,t; vector<Edge> edges; vector<int> G ; bool vis ; int d ; int cur ; void add_edge(int u,int v,int cap){ edges.push_back(Edge(u,v,cap,0)); edges.push_back(Edge(v,u,0,0)); int m = edges.size(); G[u].push_back(m-2); G[v].push_back(m-1); }; bool bfs(){ memset(vis,0,sizeof(vis)); queue<int> q; q.push(s); d[s] = 0; vis[s] =1; while(!q.empty()){ int x = q.front(); q.pop(); for(int i = 0;i<G[x].size();i++){ Edge &e = edges[G[x][i]]; if(!vis[e.to] && e.cap>e.flow){ vis[e.to] =1; d[e.to] =d[x] +1; q.push(e.to); } } } return vis[t]; } int dfs(int x,int a){ if(x == t || a== 0) return a; int flow =0,f; for(int &i = cur[x];i<G[x].size();i++){ Edge &e = edges[G[x][i]]; if(d[x] +1 == d[e.to] && (f= dfs(e.to,min(a,e.cap-e.flow)))>0){ e.flow += f; edges[G[x][i]^1].flow -=f; flow +=f; a-=f; if(!a) break; } } return flow; } int maxflow(int s,int t){ this->s = s; this->t = t; int flow = 0; while(bfs()){ memset(cur,0,sizeof(cur)); flow+=dfs(s,inf); } return flow; } }; int main(){ int m,n; while(~scanf("%d%d",&m,&n)){ Dinic ans; int arr; int sum=0; int S=m*n+1,T=m*n+2;//虚拟源点、虚拟汇点 下面是建图过程,注意如何使用模板接口。 for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ scanf("%d",&arr); sum+=arr; int num=(i-1)*n+j; if((i+j)&1){ ans.add_edge(S,num,arr); if(i>1) ans.add_edge(num,num-n,inf); if(j>1) ans.add_edge(num,num-1,inf); if(i<m) ans.add_edge(num 4000 ,num+n,inf); if(j<n) ans.add_edge(num,num+1,inf); }else ans.add_edge(num,T,arr); } } printf("%d\n",sum-ans.maxflow(S,T)); } }
相关文章推荐
- hdu 1569 方格取数(2) 网络流--最大点权独立集
- 【网络流】 HDU 1569 方格取数(2)
- 【网络流】 HDU 1569 方格取数(2)
- HDU 1565 && HDU 1569 方格取数 (网络流之最小割)
- Hdu 1569 方格取数(2) (网络流最大点权独立集)
- 【HDU 1569 方格取数(2)】 网络流
- hdu 1569 方格取数2(网络流最小割)
- 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)
- HDU1569 方格取数(2) 网络流
- HDU 1569 方格取数(2) 网络流的应用
- 【网络流】hdu 1569 方格取数(2)
- 【网络流】 hdu 1569 方格取数(2)
- 【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- hdu1569-方格取数-二分图网络流
- hdu 1569 方格取数(2) (网络流)
- 独立最小【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- hdu 1569 方格取数——最大点权独立集
- [HDU 1565+1569] 方格取数
- 二分图带权最大独立集 网络流解决 hdu 1569
- HDU 1565 方格取数(1)【网络流入门】