【网络流24题----09】方格取数问题

«问题描述:
在一个有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)



对于棋盘黑白染色构出一张二分图,二分图最大独立集。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 using namespace std;
  9 #define maxn 910
 10 #define inf 0x7fffffff
 11 #define llg int
 12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 13 llg n,m,e[maxn],N,p[10][5],g[50][50],k,tot,se[50][50];
 14
 15 struct DINIC
 16 {
 17     vector<llg>a[maxn],ba[maxn],val[maxn];
 18     llg dl[maxn],deep[maxn],bj[maxn];
 19
 20     void insert(llg x,llg y,llg z)
 21     {
 22         a[x].push_back(y),val[x].push_back(z);
 23         a[y].push_back(x),val[y].push_back(0);
 24         ba[x].push_back(a[y].size()-1); ba[y].push_back(a[x].size()-1);
 25     }
 26
 27     llg dfs(llg x,llg low)
 28     {
 29         llg va=0,inc=0;
 30         if (x==N) return low;
 31         llg w=a[x].size();
 32         for (llg i=0;i<w;i++)
 33             if (deep[x]+1==deep[a[x][i]] && val[x][i]>0 && (va=dfs(a[x][i],min(low,val[x][i]))))
 34             {
 35                 val[x][i]-=va; val[a[x][i]][ba[x][i]]+=va; inc+=va;
 36                 return va;
 37             }
 38         if (!inc) deep[x]=-1;
 39         return 0;
 40     }
 41
 42     void fencen()
 43     {
 44         llg x,w,v; deep[0]=0;
 45         memset(bj,0,sizeof(bj));
 46         llg head=0,tail=1; dl[1]=0; bj[0]=1;
 47         do
 48         {
 49             x=dl[++head]; w=a[x].size();
 50             for (llg i=0;i<w;i++)
 51             {
 52                 v=a[x][i];
 53                 if (bj[v] || val[x][i]<=0) continue;
 54                 dl[++tail]=v;
 55                 deep[v]=deep[x]+1; bj[v]=1;
 56             }
 57         }while (head!=tail);
 58     }
 59
 60     llg dinic()
 61     {
 62         llg ans=0;
 63         while (1)
 64         {
 65             fencen();
 66             if (!bj[N]) break;
 67             ans+=dfs(0,inf);
 68         }
 69         return ans;
 70     }
 71
 72     void oupt()
 73     {
 74         for (llg i=1;i<=k;i++)
 75         {
 76             printf("%d: ",i);
 77             llg w=a[i].size();
 78             for (llg e=0;e<w;e++)
 79             {
 80                 llg v=a[i][e];
 81                 if (v>k && v<N && val[i][e]==0) printf("%d ",v-k);
 82             }
 83             printf("\n");
 84         }
 85     }
 86 }G;
 87
 88 llg ma(llg x,llg y) {return x*m-m+y;}
 89
 90 void init()
 91 {
 92     p[1][1]=1,p[2][1]=-1,p[3][2]=1,p[4][2]=-1;
 93     cin>>n>>m;
 94     N=n*m+1;
 95     for (llg i=1;i<=n;i++)
 96         for (llg j=1;j<=m;j++)
 97             scanf("%d",&g[i][j]),tot+=g[i][j];
 98     for (llg i=1;i<=n;i++)
 99         for (llg j=1;j<=m;j++)
100         {
101             for (llg k=1;k<=4;k++)
102                 {
103                     llg x=i+p[k][1],y=j+p[k][2];
104                     if (x>n || x<1 || y>m || y<1) continue;
105                     se[x][y]=(se[i][j]+1)%2;
106                 }
107         }
108     for (llg i=1;i<=n;i++)
109         for (llg j=1;j<=m;j++)
110             if (se[i][j])
111             {
112                 for (llg k=1;k<=4;k++)
113                 {
114                     llg x=i+p[k][1],y=j+p[k][2];
115                     if (x>n || x<1 || y>m || y<1) continue;
116                     G.insert(ma(i,j),ma(x,y),inf);
117                 }
118                 G.insert(0,ma(i,j),g[i][j]);
119             }
120     for (llg i=1;i<=n;i++)
121         for (llg j=1;j<=m;j++)
122             if (!se[i][j])
123                 G.insert(ma(i,j),N,g[i][j]);
124 }
125
126 int main()
127 {
128     yyj("grid");
129     init();
130     cout<<tot-G.dinic();
131     return 0;
132 }
时间: 2024-08-27 12:12:28

【网络流24题----09】方格取数问题的相关文章

线性规划与网络流24题●09方格取数问题&amp;13星际转移问题

●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为"技术"不佳,搞了一上午) ●09方格取数问题(codevs1907  方格取数3) 想了半天,也没成功建好图: 无奈下参考题解,说是本题要求二分图点权最大独立集,然后可以由结论:"最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流"转化到求最大流(我真的很懵逼,但又感觉很有道理): 下面附上solution:(自己领悟吧) (不懂

LiberOJ #6007. 「网络流 24 题」方格取数 最小割 最大点权独立集 最大流

#6007. 「网络流 24 题」方格取数 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 在一个有 m×n m \times nm×n 个方格的棋盘中,每个方格中有一个正整数. 现要从方格中取数,使任意 2 22 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. 输入格式 文件第 1 11 行有 2 22 个正整数 m mm 和 n nn,分别表示棋盘的行数和列数

【网络流24题】方格取数问题

Description 在一个有m * n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于给定的方格棋盘,按照取数要求编程找出总和最大的数. Input 第1 行有2 个正整数m和n,分别表示棋盘的行数和列数. 接下来的m行,每行有n个正整数,表示棋盘方格中的数. Output 将取数的最大总和输出 Sample Input 3 3 1 2 3 3 2 3 2 3 1 Sample Output

「网络流 24 题」方格取数

大意: 给定$n*m$棋盘, 每个格子有权值, 不能选择相邻格子, 求能选出的最大权值. 二分图带权最大独立集, 转化为最小割问题. S与$X$连边权为权值的边, $X$与$Y$之间连$INF$, $Y$与$T$连边权为权值的边. 则最大权值为总权值-最小割. 残量网络中与$S$相连的或与$T$相连的表示选择, 否则表示不选. #include <iostream> #include <sstream> #include <algorithm> #include <

【网络流】hdu 1569 方格取数(2)

/* 和1565一样: 总点数的权 - 最小覆盖点集 = 最大独立集 -------------------------------------- void add(int u, int v, int f)加边 { e[ct].u = u; e[ct].v = v; e[ct].f = f; next[ct] = first[u]; first[u] = ct++; e[ct].u = v; e[ct].v = u; e[ct].f = 0; next[ct] = first[v]; first

734. [网络流24题] 方格取数问题 二分图点权最大独立集/最小割/最大流

?问题描述:在一个有m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.?编程任务:对于给定的方格棋盘,按照取数要求编程找出总和最大的数.?数据输入:由文件grid.in提供输入数据.文件第1 行有2 个正整数m和n,分别表示棋盘的行数和列数.接下来的m行,每行有n个正整数,表示棋盘方格中的数. [问题分析] 二分图点权最大独立集,转化为最小割模型,从而用最大流解决. [建模方法] 首先把棋盘黑白

线性规划与网络流9 方格取数

算法实现题 8-9 方格取数问题(习题 8-20)?问题描述:在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.?编程任务:对于给定的方格棋盘,按照取数要求编程找出总和最大的数.?数据输入:由文件 input.txt 提供输入数据.文件第 1 行有 2 个正整数 m和 n,分别表示棋盘的行数和列数.接下来的 m行,每行有 n 个正整数,表示棋盘方格中的数.?结果输出:程序运行结束时,

「网络流24题」 9. 方格取数问题

「网络流24题」 9. 方格取数问题 <题目链接> 二分图的最大点权独立集 建立二分图,使得每个点与其相邻的点在不同的部. 源向X部引有向边,Y部向汇引有向边,边权为点权. X部每个点到其相邻的点引有向边,边权INF,这个边的两个断电不能同时被选. 那么S-X-Y-T的任意一条增广路都表示选了两个相邻的点. 于是问题转化为求网络最小割. 最终的答案为所有点的点权和(先都选上)减去网络最小割(不能选的最小点权集). #include <algorithm> #include <

网络流 24题 方格取数

方格取数问题 题目描述 在一个有m*n个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. 输入格式 文件第1行有2个正整数m和n,分别表示棋盘的行数和列数.接下来的m行,每行有n个正整数,表示棋盘方格中的数.(0 <= m, n <= 30) 输出格式 取数的最大总和. 输入样例 33 1 2 3 3 2 3 2 3 1 输出样例 11 题目大意:     给出m*n的格子,相邻的格子的值不可同时取,最