• 【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.
  • 相关阅读:
    连续竞价
    使用 Sonar 进行代码质量管理
    【转】jQuery.ajax向后台传递数组问题
    DevOps
    【转】赚钱的思维
    【转】如果有人让你推荐编程技术书,请叫他看这个列表
    Java学习记录-Jdk包简单介绍
    有两个指针pa,pb分别指向有两个数,a,b,请写一个函数交换两个指针的指向,也就是让pa指向b,让pb指向a
    有两个数a,b,请写一个函数交换a,b
    开辟一个二维数组,有10*8个元素,用随机数填充,按照下面的方法用函数实现查找一个数是否存在
  • 原文地址:https://www.cnblogs.com/myx12345/p/6198508.html
Copyright © 2020-2023  润新知