zoj_2587_Unique Attack

题意:给定一个无向图,要求判定分离两个点的最小割是否唯一。

解法:在求出最大流的基础上,从源点进行一次搜索,搜索按照未饱和的边进行,得到顶点子集S的顶点个数;再从汇点反向搜索未饱和的边,得到子集T的顶点个数,判定顶点数相加是否等于总共的顶点数。

代码:

type
  arr=record
        y,w,next:longint;
      end;
var
  n,m,st,ed,nm,vs,vt,ans:longint;
  a:array [0..200001] of arr;
  ls,dis,q:array [0..1001] of longint;
  v:array [0..1001] of boolean;
procedure add(x,y,w:longint);
begin
  inc(nm);
  a[nm].y:=y; a[nm].w:=w;
  a[nm].next:=ls[x]; ls[x]:=nm;
end;

function min(o,p:longint):longint;
begin
  if o<p then exit(o);
  exit(p);
end;

function bfs:boolean;
var
  head,tail,xx,i:longint;
begin
  fillchar(v,sizeof(v),false);
  tail:=1; head:=0; dis[vt]:=1;
  v[vt]:=true; q[1]:=1;
  while head<tail do
    begin
      inc(head); xx:=q[head];
      i:=ls[xx];
      while i<>-1 do
        with a[i] do
          begin
            if (not v[y]) and (w>0) then
              begin
                v[y]:=true;
                dis[y]:=dis[xx]+1;
                if y=vt then exit(true);
                inc(tail);
                q[tail]:=y;
              end;
            i:=next;
          end;
    end;
  exit(false);
end;

function addflow(x,maxflow:longint):longint;
var
  i,o:longint;
begin
  if (x=vt) then exit(maxflow);
  addflow:=0; i:=ls[x];
  while i<>-1 do
    with a[i] do
      begin
        if (dis[y]=dis[x]+1) and (w>0) then
          begin
            o:=addflow(y,min(maxflow-addflow,w));
            if o>0 then
              begin
                inc(addflow,o);
                dec(a[i].w,o);
                inc(a[i xor 1].w,o);
                if addflow=maxflow then exit(maxflow);
              end;
          end;
        i:=next;
      end;
  if addflow=0 then dis[x]:=-1;
end;

procedure init;
var
  i,x,y,w:longint;
begin
  fillchar(ls,sizeof(ls),255);
  readln(n,m,st,ed); nm:=0;
  vs:=886; vt:=888;
  add(vs,st,maxlongint); add(st,vs,0);
  add(ed,vt,maxlongint); add(vt,ed,0);
  for i:=1 to m do
    begin
      readln(x,y,w);
      add(x,y,w); add(y,x,w);
    end;
end;

procedure getflow;
begin
  ans:=0;
  while bfs do
    ans:=ans+addflow(vs,maxlongint);
end;

procedure find_l(x:longint; var num:longint);
var
  i:longint;
begin
  i:=ls[x];
  while i<>-1 do
    begin
      if (a[i xor 1].w>0) and (not v[a[i].y]) then
        begin
          inc(num);
          v[a[i].y]:=true;
          find_l(a[i].y,num);
        end;
      i:=a[i].next;
    end;
end;

procedure find_r(x:longint; var num:longint);
var
  i:longint;
begin
  i:=ls[x];
  while i<>-1 do
    begin
      if (a[i xor 1].w>0) and (not v[a[i].y]) then
        begin
          inc(num);
          v[a[i].y]:=true;
          find_r(a[i].y,num);
        end;
      i:=a[i].next;
    end;
end;

procedure print;
var
  anum,bnum:longint;
begin
  anum:=0; bnum:=0;
  fillchar(v,sizeof(v),false);
  v[vs]:=true; v[vt]:=true;
  find_l(vs,anum);
  fillchar(v,sizeof(v),false);
  v[vs]:=true; v[vt]:=true;
  find_r(vt,bnum);
  if anum+bnum=n then writeln('UNIQUE')
                 else writeln('AMBIGUOUS');
end;

begin
  init;
  getflow;
  print;
end.

上面代码是假的。

原文地址:https://www.cnblogs.com/zyx-crying/p/9319504.html