[vijos P1524] 最小监视代价

历时四天(本周三至本周六),本人的第一道网络流题目终于通过了…虽然这么慢才搞懂很大程度是因为脑子笨,但是还是要吐槽一下:

(1)选的这道题吧居然是无向图,对于初学者我表示呵呵,昨晚到现在一直在纠结怎么搞。一开始觉得在循环里加个j=0就好了,后来发现运行速度慢以为错了,后来才发现是自作聪明把书上一行代码给去掉了…QAQ

(2)这道题是多汇点,一开始还以为有x个汇点运行x次取最大呢,又脑残了;

(3)我的教材…写的是手动栈,虽然这免除了溢出,但是长度堪忧啊QAQ,而且数据才100根本不会溢出的啊…Anyway有空要把递归写法给写一下,不过手工栈的确很久没有码过了~~

至少这么一折腾,算是差不多懂了一些网络流算法,有空学一下Dinic。还有一周就要考试了,纯属酱油心态的我也要加油啦~

f表示flow也就是存储流,findpath和adjust这两个子段的名字太浅显了不解释了…s是手工栈。

program vijos_p1524;
var map,f:array[0..101,0..101] of longint;
    s,mark:array[-1..101] of integer;
    n,e,m,a,b,w,x,i,j:integer;
    ans,anst,top:longint;
function findpath:boolean;
begin
  fillchar(mark,sizeof(mark),0);
  i:=1;j:=0;mark[1]:=1;top:=1;s[top]:=1;
  repeat
    i:=abs(s[top]);
    repeat
      j:=j+1;
      if (mark[j]=0) and (map[i,j]<>0) then
        begin
          if map[i,j]>f[i,j] then
            begin
              inc(top);s[top]:=j;
              mark[j]:=1;
            end
          else
            if f[j,i]>0 then
              begin
                inc(top);s[top]:=-j;
                mark[j]:=1;
              end;
        end;
    until (j>=n+1) or (i<>abs(s[top]));
    if i=abs(s[top]) then
      begin
        j:=abs(s[top]);
        mark[abs(s[top])]:=0;
        s[top]:=0;
        dec(top);
      end
    else j:=0;
  until (top=0) or (s[top]=x);
  findpath:=(top>0);
end;

procedure adjust;
var i,j,k,x,z:longint;
begin
  k:=1;i:=s[k];z:=maxlongint;
  repeat
    inc(k);j:=s[k];
    if j<0 then x:=f[-j,i] else x:=map[i,j]-f[i,j];
    if x<z then z:=x;
    i:=abs(j);
  until k=top;
  k:=1;i:=s[k];
  repeat
    inc(k);j:=s[k];
    if j<0 then
      begin
        f[-j,i]:=f[-j,i]-z;
      end
    else
      begin
        f[i,j]:=f[i,j]+z;
      end;
    i:=abs(j);
  until k=top;
end;


procedure work;
var j:integer;
begin
  fillchar(f,sizeof(f),0);
  anst:=0;
  while findpath do adjust;
  for j:=1 to n+1 do
    anst:=anst+f[1,j];
end;

begin
  readln(n,e);
  for i:=1 to e do
    begin
      readln(a,b,w);
      map[a,b]:=w;map[b,a]:=w;
    end;
  readln(m);
  for i:=1 to m do
    begin
      read(x);
      map[x,n+1]:=maxlongint;
    end;
  x:=n+1;{top:=1;s[top]:=1;mark[1]:=1;j:=0;}
  work;
  writeln(anst);
end.
最小监视代价
原文地址:https://www.cnblogs.com/Sky-Grey/p/3617487.html