狼抓兔子(平面图转对偶图求最短路)

一个网格图中求最小割,很特殊的是这个图是一个平面图,最小割=最大流=对偶图中最短路,把小三角换成点标号,重连边即可。

我标号用的矩阵元素标号的思想,可能看着还算清楚,乘来乘去的。

数据里还有n == 1m == 1的数据。。。。。

插个图片帮助理解。

View Code
  1 program beijing2006(input,output);
  2 const
  3    oo = 999999999;
  4 type
  5    node    = ^link;
  6    link    = record
  7          goal,w : longint;
  8          next   : node;
  9       end;
 10 var
 11    l           : array[0..2500000] of node;
 12    d           : array[0..2500000] of int64;
 13    v           : array[0..2500000] of boolean;
 14    q           : array[0..2500000] of longint;
 15    n,m,sum     : longint;
 16    start,final : longint;
 17 procedure add(xx,yy,ww: longint );
 18 var
 19    tt : node;
 20 begin
 21    new(tt);
 22    tt^.goal:=yy;
 23    tt^.w:=ww;
 24    tt^.next:=l[xx];
 25    l[xx]:=tt;
 26 end; { add }
 27 function check():boolean;
 28 var
 29    i,x      : longint;
 30    answer : int64;
 31 begin
 32    answer:=oo;
 33    if n=1 then
 34    begin
 35       for i:=1 to m-1 do
 36       begin
 37      read(x);
 38      if x<answer then
 39         answer:=x;
 40       end;
 41       writeln(answer);
 42       exit(true);
 43    end;
 44    if m=1 then
 45    begin
 46       for i:=1 to n-1 do
 47       begin
 48      read(x);
 49      if x<answer then
 50         answer:=x;
 51       end;
 52       writeln(answer);
 53       exit(true);
 54    end;
 55    exit(false);
 56 end; { check }
 57 procedure init;
 58 var
 59    i : longint;
 60 begin
 61    readln(n,m);
 62    for i:=0 to 2*m*n+3 do
 63       l[i]:=nil;
 64    sum:=(n-1)*(m-1);
 65    Start:=0;
 66    final:=(m-1)+(m-1)*2*(n-1)+1;
 67 end; { init }
 68 procedure make_graph;
 69 var
 70    i,j : longint;
 71    ww  : longint;
 72 begin
 73    for i:=1 to n do
 74       for j:=1 to m-1 do
 75       begin
 76      read(ww);
 77      if i=1 then
 78      begin
 79         add(final,(i*(m-1)+j)+sum,ww);
 80         add((i*(m-1)+j)+sum,final,ww);
 81      end
 82      else
 83         if i=n then
 84         begin
 85            add((i-1)*(m-1)+j,start,ww);
 86            add(start,(i-1)*(m-1)+j,ww);
 87         end
 88         else
 89         begin
 90            add((i-1)*(m-1)+j,i*(m-1)+j+sum,ww);
 91            add(i*(m-1)+j+sum,(i-1)*(m-1)+j,ww);
 92         end;
 93       end;
 94    for i:=1 to n-1 do
 95       for j:=1 to m do
 96       begin
 97      read(ww);
 98      if j=1 then
 99      begin
100         add(start,i*(m-1)+j,ww);
101         add(i*(m-1)+j,start,ww);
102      end
103      else
104         if j=m then
105         begin
106            add(final,i*(m-1)+j-1+sum,ww);
107            add(i*(m-1)+j-1+sum,final,ww);
108         end
109         else
110         begin
111            add(i*(m-1)+j,i*(m-1)+j-1+sum,ww);
112            add(i*(m-1)+j-1+sum,i*(m-1)+j,ww);
113         end;
114       end;
115    for i:=1 to n-1 do
116       for j:=1 to m-1 do
117       begin
118      read(ww);
119      add(i*(m-1)+j,i*(m-1)+j+sum,ww);
120      add(i*(m-1)+j+sum,i*(m-1)+j,ww);
121       end;
122 end; { make_graph }
123 procedure spfa();
124 var
125    head,tail : longint;
126    t         : node;
127 begin
128    fillchar(v,sizeof(v),false);
129    fillchar(d,sizeof(d),63);
130    head:=0;
131    tail:=1;
132    v[start]:=true;
133    q[1]:=start;
134    d[start]:=0;
135    while head<>tail do
136    begin
137       inc(head);
138       if head=2500000 then
139      head:=0;
140       v[q[head]]:=false;
141       t:=l[q[head]];
142       while t<>nil do
143       begin
144      if d[q[head]]+t^.w<d[t^.goal] then
145      begin
146         d[t^.goal]:=d[q[head]]+t^.w;
147         if not v[t^.goal] then
148         begin
149            inc(tail);
150            if tail=2500000 then
151           tail:=0;
152            q[tail]:=t^.goal;
153            v[t^.goal]:=true;
154         end;
155      end;
156      t:=t^.next;
157       end;
158    end;
159 end; { spfa }
160 procedure print;
161 begin
162    writeln(d[final]);
163 end; { print }
164 begin
165    init;
166    if not check() then
167    begin
168       make_graph();
169       spfa();
170       print;
171    end;
172 end.

 

 

 

转载于:https://www.cnblogs.com/neverforget/archive/2012/04/16/2452190.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值