zoukankan      html  css  js  c++  java
  • bzoj1001

    平面图求最小割;

    其实看bzoj1001一开始着实把我怔住了

    AC的人暴多,可自己完全没思路

    后来看了某大牛的ppt,才会做

    一个月前做这题的吧,今天来简单回忆一下;

    首先是欧拉公式

    如果一个连通的平面图有n个点,m条边和f个面,那么f=m-n+2

    我们把原图的每个面看成新图的一个点,对于原图中的每条边

    如果边只属于一个面,那么给对应点连一个自环;

    如果边两侧各有一个面,那么给对应点之间连一条无向边

    这样,新图与原图的边一一对应;

    可以发现,新图的一条路径对应原图的一个割

    于是我们原图起点终点连一条边,增加一个附加面(也可以理解为把外面言直线st分为两个面);

    按上述方法建新图,于是最小割问题转化为对新图求最短路;

    最短路可以用堆优化dij;

    这题我的dij+heap写的有进步

      1 const inf=2147483647;
      2 type link=^node;
      3      node=record
      4        po,len:longint;
      5        next:link;
      6      end;
      7      point=record
      8        num,loc:longint;
      9      end;
     10 
     11 var w:array[0..2020010] of link;
     12     heap:array[0..2020010] of point;
     13     where,d:array[0..2020010] of longint;
     14     xie,hen,shu:array[0..1010,0..1010] of longint;
     15     t,s,i,j,n,m,x,y:longint;
     16     p:link;
     17 
     18 procedure swap(var a,b:point);
     19   var c:point;
     20   begin
     21     c:=a;
     22     a:=b;
     23     b:=c;
     24   end;
     25 
     26 procedure add(x,y,z:longint);
     27   var p:link;
     28   begin
     29     new(p);
     30     p^.po:=y;
     31     p^.len:=z;
     32     p^.next:=w[x];
     33     w[x]:=p;
     34   end;
     35 
     36 procedure up(i:longint);
     37   var j,x,y:longint;
     38   begin
     39     j:=i shr 1;
     40     while j>0 do
     41     begin
     42       if heap[i].num<heap[j].num then
     43       begin
     44         x:=heap[i].loc;
     45         y:=heap[j].loc;
     46         where[x]:=j;
     47         where[y]:=i;
     48         swap(heap[i],heap[j]);
     49         i:=j;
     50         j:=i shr 1;
     51       end
     52       else break;
     53     end;
     54   end;
     55 
     56 procedure sift(i:longint);
     57   var j,x,y:longint;
     58   begin
     59     j:=i shl 1;
     60     while j<=s do
     61     begin
     62       if (j+1<=s) and (heap[j].num>heap[j+1].num) then inc(j);
     63       if heap[i].num>heap[j].num then
     64       begin
     65         x:=heap[i].loc;
     66         y:=heap[j].loc;
     67         where[x]:=j;
     68         where[y]:=i;
     69         swap(heap[i],heap[j]);
     70         i:=j;
     71         j:=i shl 1;
     72       end
     73       else break;
     74     end;
     75   end;
     76 
     77 procedure build;    //复杂的建图,这种东西一定要谨慎,错误才会少;
     78   var i:longint;
     79   begin
     80     for i:=1 to m-1 do
     81     begin
     82       add(1,i+1,hen[1,i]);
     83       add(i+1,1,hen[1,i]);
     84     end;
     85     for i:=1 to n-1 do
     86     begin
     87       x:=(m-1)*(2*i-1)+1;
     88       add(1,x,shu[i,m]);
     89       add(x,1,shu[i,m]);
     90     end;
     91 
     92     for i:=1 to m-1 do
     93     begin
     94       x:=t-m+i;
     95       add(t,x,hen[n,i]);
     96       add(x,t,hen[n,i]);
     97     end;
     98     for i:=1 to n-1 do
     99     begin
    100       x:=(m-1)*(2*i-1)+2;
    101       add(t,x,shu[i,1]);
    102       add(x,t,shu[i,1]);
    103     end;
    104 
    105     for i:=2 to n-1 do
    106       for j:=1 to m-1 do
    107       begin
    108         x:=(2*i-3)*(m-1)+j+1;
    109         y:=x+m-1;
    110         add(x,y,hen[i,j]);
    111         add(y,x,hen[i,j]);
    112       end;
    113 
    114     for i:=1 to n-1 do
    115       for j:=2 to m-1 do
    116       begin
    117         x:=(2*i-2)*(m-1)+j;
    118         y:=x+m;
    119         add(x,y,shu[i,j]);
    120         add(y,x,shu[i,j]);
    121       end;
    122 
    123     for i:=1 to n-1 do
    124       for j:=1 to m-1 do
    125       begin
    126         x:=(2*i-2)*(m-1)+j+1;
    127         y:=x+m-1;
    128         add(x,y,xie[i,j]);
    129         add(y,x,xie[i,j]);
    130       end;
    131   end;
    132 
    133 procedure dij;       //最短路
    134   var p:link;
    135       mid,k,y:longint;
    136   begin
    137     p:=w[1];
    138     for i:=2 to t do
    139       d[i]:=inf;
    140     d[1]:=0;
    141     while p<>nil do
    142     begin
    143       x:=p^.po;
    144       d[x]:=min(d[x],p^.len);
    145       p:=p^.next;
    146     end;
    147     s:=0;
    148     for i:=2 to t do
    149     begin
    150       inc(s);
    151       heap[s].num:=d[i];
    152       heap[s].loc:=i;        //表示堆的这个位置是哪个点
    153       where[i]:=s;           //where表示这个点在堆的哪个位置
    154       up(s);
    155     end;
    156 
    157     for k:=1 to t do
    158     begin
    159       mid:=heap[1].num;
    160       if s=0 then break;      
    161       if mid=inf then break;   
    162       x:=heap[1].loc;
    163       y:=heap[s].loc;
    164       where[y]:=1;
    165 
    166       swap(heap[1],heap[s]);   //退堆
    167       dec(s);
    168 
    169       sift(1);
    170       p:=w[x];
    171       while p<>nil do
    172       begin
    173         y:=p^.po;
    174         if d[y]>p^.len+mid then     //更新,入堆
    175         begin
    176           d[y]:=p^.len+mid; 
    177           heap[where[y]].num:=d[y];
    178           up(where[y]);
    179         end;
    180         p:=p^.next;
    181       end;
    182     end;
    183   end;
    184 
    185 begin
    186   readln(n,m);
    187   for i:=1 to n do
    188   begin
    189     for j:=1 to m-1 do
    190       read(hen[i,j]);
    191   end;
    192   for i:=1 to n-1 do
    193   begin
    194     for j:=1 to m do
    195       read(shu[i,j]);
    196   end;
    197   for i:=1 to n-1 do
    198   begin
    199     for j:=1 to m-1 do
    200       read(xie[i,j]);
    201   end;
    202 
    203   if n=1 then       //注意这种情况要特判
    204   begin
    205     t:=inf;
    206     for i:=1 to m-1 do
    207       t:=min(hen[1,i],t);
    208     writeln(t);
    209     halt;
    210   end
    211   else if m=1 then
    212   begin
    213     t:=inf;
    214     for i:=1 to n-1 do
    215       t:=min(t,shu[i,1]);
    216     writeln(t);
    217     halt;
    218   end;
    219   t:=(n-1)*(m-1)*2+2;    //计算新图总点数
    220   build;
    221   dij;
    222   writeln(d[t]);
    223 end.
    View Code
  • 相关阅读:
    Sybase:游标用法以及嵌套用法
    EasyUI:获取某个dategrid的所有行数据
    EasyUI:所有的图标
    Sybase:SAP IQ学习笔记
    Sybase:SybaseIQ的几个系统过程
    Sybase:解锁
    Python3:文件读写
    Android Studio 1.0.2 设置内存大小
    关于Android的margin(当前视图与周围视图的距离)和padding(当前视图与内部内容的距离)
    《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误
  • 原文地址:https://www.cnblogs.com/phile/p/4473261.html
Copyright © 2011-2022 走看看