bzoj1934 bzoj2768

时间:2022-12-01 23:14:30

最小割的经典模型,体现出最小割的基本定义,把两个集合划分的最小代价

把一开始同意的人连源点,不同意的连汇点,有关系的人之间连边,流量都为1

不难发现,割两点(人)间的边就相当于朋友之间发生冲突

割到连源汇点的边就相当于与原来意愿不同

所以解决问题的方案等于图中的一个割

则最少冲突数=最小割=最大流

 type node=record
       point,flow,next:longint;
     end;
var edge:array[..] of node;
    cur,p,pre,numh,h:array[..] of longint;
    ans,len,i,j,x,y,n,m:longint; procedure add(x,y,f:longint);
  begin
    inc(len);
    edge[len].point:=y;
    edge[len].flow:=f;
    edge[len].next:=p[x];
    p[x]:=len;
  end; procedure sap;
  var tmp,u,i,j,neck,f,q:longint;
  begin
    u:=;
    numh[]:=n+;
    fillchar(pre,sizeof(pre),);
    fillchar(cur,sizeof(cur),);
    while h[]<n+ do
    begin
      if u=n then
      begin
        i:=;
        while i<>n do
        begin
          j:=cur[i];
          dec(edge[j].flow);
          inc(edge[j xor ].flow);
          i:=edge[j].point;
        end;
        inc(ans);
        u:=;
      end;
      q:=-;
      i:=p[u];
      while i<>- do
      begin
        j:=edge[i].point;
        if (edge[i].flow>) and (h[u]=h[j]+) then
        begin
          q:=i;
          break;
        end;
        i:=edge[i].next;
      end;
      if q<>- then
      begin
        cur[u]:=q;
        pre[j]:=u;
        u:=j;
      end
      else begin
        dec(numh[h[u]]);
        if numh[h[u]]= then break;
        i:=p[u];
        tmp:=n+;
        while i<>- do
        begin
          j:=edge[i].point;
          if (edge[i].flow>) then tmp:=min(tmp,h[j]);
          i:=edge[i].next;
        end;
        h[u]:=tmp+;
        inc(numh[h[u]]);
        if u<> then u:=pre[u];
      end;
    end;
  end; begin
  readln(n,m);
  len:=-;
  fillchar(p,sizeof(p),);
  for i:= to n do
  begin
    read(x);
    if x= then
    begin
      add(,i,);
      add(i,,);
    end
    else begin
      add(i,n+,);
      add(n+,i,);
    end;
  end;
  for i:= to m do
  begin
    readln(x,y);
    add(x,y,);
    add(y,x,);
    add(y,x,);
    add(x,y,);
  end;
  inc(n);
  sap;
  writeln(ans);
end.