hdu 1565 方格取数(神奇的最小割,模板题)
2017-10-12 12:24
323 查看
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=1565
思路:
最大流最小割:最大和=所有数之和—最小割(网络流)
建图:奇数点连源点,然后以inf为容量连周围偶数点,偶数点连汇点。
思路:
最大流最小割:最大和=所有数之和—最小割(网络流)
建图:奇数点连源点,然后以inf为容量连周围偶数点,偶数点连汇点。
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<iostream> #define mem(a,x) memset(a,x,sizeof(a)) using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 50 + 5; const int maxs = maxn*maxn + 5; int n,m,source,sink; int mp[maxn][maxn]; struct Edge{ int from,to,cap,flow; }; struct Dicnic{ int n,m,s,t; int d[maxs],cur[maxs],vis[maxs]; vector<int>G[maxs]; vector<Edge>edges; void AddEdge(int from,int to,int cap){ Edge e1 = {from,to,cap,0}; Edge e2 = {to,from,0,0}; edges.push_back(e1); edges.push_back(e2); int m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } void init(int n){ this -> n = n; for(int i = 0;i<=n;i++){ G[i].clear(); } edges.clear(); } bool BFS(){ //就是用BFS分了个层而已,一看代码便知 mem(vis,0); queue<int>Q; Q.push(s); vis[s] = 1; d[s] = 0; //mem(d,0); 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){ //就是顺着层次dfs而已 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[e.to]==d[x]+1&&(f = DFS(e.to,min(a,e.cap-e.flow)))>0){ //a是路径上的最小残存容量 e.flow += f; edges[G[x][i]^1].flow -= f; //反向边 flow += f; a -= f; if(a==0) break; //a等于0及时退出,再从s那找一遍,因为从哪断的不知道 } } return flow; } int MaxFlow(int s,int t){ this -> s = s; this ->t = t; int flow = 0; while(BFS()){ mem(cur,0); flow += DFS(s,inf); } return flow; } }g; int drx[] = {0,1,0,-1}; int dry[] = {1,0,-1,0}; bool valid(int x,int y){ if(x<1||x>n||y<1||y>m) return false; else return true; } int id(int x,int y){ return (x-1)*m + y; } int main(){ while(scanf("%d",&n)!=EOF){ m=n; g.init(n*m + 1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&mp[i][j]); source = 0 ; sink = n * m + 1; int sum=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if((i+j)%2==1){ g.AddEdge(source,id(i,j),mp[i][j]); for(int k = 0;k<4;k++){ int nx = i + drx[k]; int ny = j + dry[k]; if(valid(nx,ny)) g.AddEdge(id(i,j),id(nx,ny),inf); } } else{ g.AddEdge(id(i,j),sink,mp[i][j]); } sum+=mp[i][j]; } int ans = g.MaxFlow(source,sink); printf("%d\n",sum-ans); } return 0; } /* 6 0 31 1231 12 1 21 13 135 1321 1 3 21 132 132 5 15 3 12 13 453 321 45 0 0 35 534 4 531 124 12 13 135 1321 1 3 21 */
相关文章推荐
- hdu 1565 方格取数(1)(最小割--最大权独立点集)
- 方格取数 hdu 1565 最小割
- hdu1565 hdu1569 方格取数 最小割
- HDU 1565 1569 方格取数 (最小割)
- hdu 1565 方格取数(1) (最小割/状态压缩+DP)
- hdu 1565 方格取数(1)(最小割,最大点权独立集)
- HDU 1565 && HDU 1569 方格取数 (网络流之最小割)
- HDU 1565 方格取数(1)(最大独立点权覆盖 | 最小割)
- HDU 1565 方格取数(1) (最小权值独立集)
- hdu 1565 方格取数(1)/hdu 1569 方格取数(2)(最小割,黑白染色)
- 最小割的应用--方格取数问题(HDU 1565,HDU 1569)
- hdu 1565 方格取数(1)(最小割)
- hdu1565 方格取数(1)&&hdu1569 方格取数(2)(最小割)
- HDU 1565 方格取数(1)(最小割-Dinic)
- HDU 1565 方格取数(1)
- HDU 2122(最小生成树模板)
- hdu 1565 方格取数(1)
- 【HDU】3452 Bonsai 最小割模板题
- HDU_1569 方格取数(2) 最小割
- 最小生成树模板(POJ 1258-prime+HDU 1233 Kruskal为例)