Codevs1907方格取数3(最小割)
Posted myx12345
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codevs1907方格取数3(最小割)相关的知识,希望对你有一定的参考价值。
题意:在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
n,m<=30
思路:如果将棋盘黑白点染色,可以发现相邻的黑白点不能同时取
将源点到黑点连一条容量为黑点数字的边,黑点到相邻白点连容量为∞的边,白点到汇点连容量为白点数字的边,可以发现如果不让相邻黑白点同时取到,三条边中必定要切断一条
题意就是让切断的总和最小,所以显然不会切∞,只会切另外两条
跑最小割即可
1 const dx:array[1..4]of longint=(-1,1,0,0); 2 dy:array[1..4]of longint=(0,0,-1,1); 3 var fan:array[1..200000]of longint; 4 head,vet,next,len,gap,dis:array[0..20000]of longint; 5 a,b,num:array[1..50,1..50]of longint; 6 n,m,i,j,tot,source,src,s,sum,k,x,y:longint; 7 8 function min(x,y:longint):longint; 9 begin 10 if x<y then exit(x); 11 exit(y); 12 end; 13 14 procedure add(a,b,c:longint); 15 begin 16 inc(tot); 17 next[tot]:=head[a]; 18 vet[tot]:=b; 19 len[tot]:=c; 20 head[a]:=tot; 21 22 inc(tot); 23 next[tot]:=head[b]; 24 vet[tot]:=a; 25 len[tot]:=0; 26 head[b]:=tot; 27 end; 28 29 function dfs(u,aug:longint):longint; 30 var e,v,t,val,flow:longint; 31 begin 32 if u=src then exit(aug); 33 e:=head[u]; val:=s-1; flow:=0; 34 while e<>0 do 35 begin 36 v:=vet[e]; 37 if len[e]>0 then 38 begin 39 if dis[u]=dis[v]+1 then 40 begin 41 t:=dfs(v,min(len[e],aug-flow)); 42 len[e]:=len[e]-t; 43 len[fan[e]]:=len[fan[e]]+t; 44 flow:=flow+t; 45 if dis[source]>=s then exit(flow); 46 if aug=flow then break; 47 end; 48 val:=min(val,dis[v]); 49 end; 50 e:=next[e]; 51 end; 52 if flow=0 then 53 begin 54 dec(gap[dis[u]]); 55 if gap[dis[u]]=0 then dis[source]:=s; 56 dis[u]:=val+1; 57 inc(gap[dis[u]]); 58 end; 59 exit(flow); 60 end; 61 62 63 function maxflow:longint; 64 var ans:longint; 65 begin 66 fillchar(gap,sizeof(gap),0); 67 fillchar(dis,sizeof(dis),0); 68 gap[0]:=s; ans:=0; 69 while dis[source]<s do ans:=ans+dfs(source,maxlongint); 70 exit(ans); 71 end; 72 73 begin 74 assign(input,‘Codevs1907.in‘); reset(input); 75 assign(output,‘Codevs1907.out‘); rewrite(output); 76 readln(n,m); 77 for i:=1 to 200000 do 78 if i mod 2=1 then fan[i]:=i+1 79 else fan[i]:=i-1; 80 for i:=1 to n do 81 for j:=1 to m do 82 begin 83 read(a[i,j]); sum:=sum+a[i,j]; 84 inc(s); num[i,j]:=s; b[i,j]:=(i+j+1) mod 2; 85 end; 86 for i:=1 to n do 87 for j:=1 to m do 88 if b[i,j]=1 then 89 for k:=1 to 4 do 90 begin 91 x:=i+dx[k]; y:=j+dy[k]; 92 if (x>0)and(x<=n)and(y>0)and(y<=m) then 93 begin 94 add(num[i,j],num[x,y],maxlongint); 95 //writeln(i,‘ ‘,j,‘ ‘,x,‘ ‘,y); 96 end; 97 end; 98 source:=s+1; src:=s+2; s:=s+2; 99 for i:=1 to n do 100 for j:=1 to m do 101 if b[i,j]=1 then 102 begin 103 //writeln(source,‘ ‘,i,‘ ‘,j); 104 add(source,num[i,j],a[i,j]); 105 end 106 else 107 begin 108 //writeln(i,‘ ‘,j,‘ ‘,src); 109 add(num[i,j],src,a[i,j]); 110 end; 111 writeln(sum-maxflow); 112 113 close(input); 114 close(output); 115 end.
以上是关于Codevs1907方格取数3(最小割)的主要内容,如果未能解决你的问题,请参考以下文章