【codevs1907】方格取数3(最大流最小割定理)
网址:http://codevs.cn/problem/1907/
题意:在一个矩阵里选不相邻的若干个数,使这些数的和最大。
我们可以把它看成一个最小割,答案就是矩阵中的所有数-最小割。先把矩阵按国际象棋棋盘黑白染色(即把相邻的点分别染成白色和黑色),然后黑点连源点,白点连汇点。割掉一个点到源/汇的边就是不选择这个点,最后的目的就是使源到汇不连通(不引发题目不能选择位置相邻的数的矛盾)。
然而最小割怎么求呢?
于是我们就要引入一个定理:最大流最小割定理。它的意思就是说,在一个图中,a点到b点的最小割=a到b的最大流。
然而我并不会证……这里口胡一个想法:最大流就是沿着剩余网络不断地流,每流一次相当于删掉剩余网络的一条边,流到不能流为止。而最小割也是不断地割直到不连通。于是最小割=最大流。
答案就这样变成了求最大流。
具体怎么建图,就是把黑/白点到源/汇的边的流量定为这个位置的上数,而黑白点之间的边,因为不能把它割掉,所以把它的流量设为一个极大数。
于是就过了。
代码:
var a:array[..,..]of longint;
s:array[..,..]of longint;
l,q:array[..]of longint;
n,m,nn,i,j,k,h,t:longint;
ans,sum:int64;
function num(x,y:longint):longint;
begin
exit((x-)*m+y);
end;
function dfs(now,ll:longint):longint;
var p,i:longint;
begin
if now=nn then exit(ll);
for i:= to nn do
if(a[now,i]>)and(l[i]=l[now]+)then begin
if a[now,i]<ll then p:=dfs(i,a[now,i])
else p:=dfs(i,ll);
a[now,i]:=a[now,i]-p; a[i,now]:=a[i,now]+p;
if p> then exit(p);
end;
exit();
end;
begin
read(n,m); sum:=;
for i:= to n do
for j:= to m do begin
read(s[i,j]);
sum:=sum+s[i,j];
end;
fillchar(a,sizeof(a),);
for i:= to n do
for j:= to m do
if (i+j)and = then a[num(i,j),n*m+]:=s[i,j]
else begin
if i> then a[num(i,j),num(i-,j)]:=<<;
if i<n then a[num(i,j),num(i+,j)]:=<<;
if j> then a[num(i,j),num(i,j-)]:=<<;
if j<m then a[num(i,j),num(i,j+)]:=<<;
a[,num(i,j)]:=s[i,j];
end;
nn:=n*m+; ans:=;
while true do begin
fillchar(l,sizeof(l),);
h:=; t:=; q[]:=; l[]:=;
repeat
for i:= to nn do
if(a[q[h],i]>)and(l[i]=)then begin
inc(t); q[t]:=i; l[i]:=l[q[h]]+;
end;
inc(h);
until h>t;
if l[nn]= then break;
repeat
k:=dfs(,<<);
ans:=ans+k;
until k=;
end;
writeln(sum-ans);
end.
codevs1907方格取数
【codevs1907】方格取数3(最大流最小割定理)的更多相关文章
- HDU 1569 方格取数(2) (最小割)
方格取数(2) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- [BZOJ1475]方格取数 网络流 最小割
1475: 方格取数 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1025 Solved: 512[Submit][Status][Discuss] ...
- LuoguP2774 方格取数问题(最小割)
题目背景 none! 题目描述 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于 ...
- codevs1907 方格取数 3
«问题描述:在一个有m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.«编程任务:对于给定的方格棋 ...
- 【bzoj1475】方格取数 网络流最小割
题目描述 在一个n*n的方格里,每个格子里都有一个正整数.从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大. 输入 第一行一个数n:(n<=30) 接下来n行每行n ...
- 洛谷P2774 方格取数问题(最小割)
题意 $n \times m$的矩阵,不能取相邻的元素,问最大能取多少 Sol 首先补集转化一下:最大权值 = sum - 使图不连通的最小权值 进行黑白染色 从S向黑点连权值为点权的边 从白点向T连 ...
- luogu2774 [网络流24题]方格取数问题 (最小割)
常见套路:棋盘黑白染色,就变成了一张二分图 然后如果选了黑点,四周的白点就不能选了,也是最小割的套路.先把所有价值加起来,再减掉一个最少的不能选的价值,也就是割掉表示不选 建边(S,黑点i,v[i]) ...
- 线性规划与网络流24题●09方格取数问题&13星际转移问题
●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为“技术”不佳,搞了一上午) ●09方格取数问题(codevs1907 方格取数3) 想了半天,也没成功建好图: 无奈下 ...
- 「网络流24题」「LuoguP2774」方格取数问题(最大流 最小割
Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于给定的方 ...
随机推荐
- vue起手式
主要步骤 安装node 安装npm 安装vue-cli(vue命令行工具) 初始化一个vue项目 进行开发 # 安装node # 安装npm # 安装cnpm,在中国大陆防止被墙 # 安装git # ...
- filter、map函数的区别
def even(num): if num%2==0: return True return False lis = [1,2,3,4,5,6,7,8,9] res = filter(even,lis ...
- P2424 约数和
题目背景 Smart最近沉迷于对约数的研究中. 题目描述 对于一个数X,函数f(X)表示X所有约数的和.例如:f(6)=1+2+3+6=12.对于一个X,Smart可以很快的算出f(X).现在的问题是 ...
- 关于自我总结的html5新特性
最近本包子制订了一个学校计划,第一步就是了解并总结一下html5现在所含有的新特性,好吧,这只是一个了解,- -! 自己总结了一个word文档,里面很多东西自己都还没实际用过,下一步,本包子要写pc端 ...
- ajax异步请求分页显示
html代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- 介绍一下except的用法和作用?
Python的except用来捕获所有异常,因为Python里面的每次错误都会抛出一个异常,所以每个程序的错误都被当作一个运行时错误.
- python多进程编程(二)
进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进 ...
- Linxu下jenkins部署和基本配置
一.OpenJdk1.8安装(tomcat 和 jenkins都依赖与java) ubuntu apt-cache search openjdk #使用apt-cache搜索可以直接使用 ...
- Python2 socket 多线程并发 TCPServer Demo
#coding=utf-8 import socket import threading,getopt,sys,string opts, args = getopt.getopt(sys.argv[1 ...
- python基础27 -----python进程终结篇-----IO模型
一.IO模型 1.IO模型分类 1.阻塞IO--------blocking IO 2.非阻塞IO------nonblocking IO 3. 多路复用IO------- multiplexing ...