随笔 - 540  文章 - 0 评论 - 39 trackbacks - 0

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

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

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

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

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

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

  1 type node=record
  2        point,flow,next:longint;
  3      end;
  4 var edge:array[0..400010] of node;
  5     cur,p,pre,numh,h:array[0..2010] of longint;
  6     ans,len,i,j,x,y,n,m:longint;
  7 
  8 procedure add(x,y,f:longint);
  9   begin
 10     inc(len);
 11     edge[len].point:=y;
 12     edge[len].flow:=f;
 13     edge[len].next:=p[x];
 14     p[x]:=len;
 15   end;
 16 
 17 procedure sap;
 18   var tmp,u,i,j,neck,f,q:longint;
 19   begin
 20     u:=0;
 21     numh[0]:=n+1;
 22     fillchar(pre,sizeof(pre),255);
 23     fillchar(cur,sizeof(cur),255);
 24     while h[0]<n+1 do
 25     begin
 26       if u=n then
 27       begin
 28         i:=0;
 29         while i<>n do
 30         begin
 31           j:=cur[i];
 32           dec(edge[j].flow);
 33           inc(edge[j xor 1].flow);
 34           i:=edge[j].point;
 35         end;
 36         inc(ans);
 37         u:=0;
 38       end;
 39       q:=-1;
 40       i:=p[u];
 41       while i<>-1 do
 42       begin
 43         j:=edge[i].point;
 44         if (edge[i].flow>0) and (h[u]=h[j]+1) then
 45         begin
 46           q:=i;
 47           break;
 48         end;
 49         i:=edge[i].next;
 50       end;
 51       if q<>-1 then
 52       begin
 53         cur[u]:=q;
 54         pre[j]:=u;
 55         u:=j;
 56       end
 57       else begin
 58         dec(numh[h[u]]);
 59         if numh[h[u]]=0 then break;
 60         i:=p[u];
 61         tmp:=n+1;
 62         while i<>-1 do
 63         begin
 64           j:=edge[i].point;
 65           if (edge[i].flow>0) then tmp:=min(tmp,h[j]);
 66           i:=edge[i].next;
 67         end;
 68         h[u]:=tmp+1;
 69         inc(numh[h[u]]);
 70         if u<>0 then u:=pre[u];
 71       end;
 72     end;
 73   end;
 74 
 75 begin
 76   readln(n,m);
 77   len:=-1;
 78   fillchar(p,sizeof(p),255);
 79   for i:=1 to n do
 80   begin
 81     read(x);
 82     if x=0 then
 83     begin
 84       add(0,i,1);
 85       add(i,0,0);
 86     end
 87     else begin
 88       add(i,n+1,1);
 89       add(n+1,i,0);
 90     end;
 91   end;
 92   for i:=1 to m do
 93   begin
 94     readln(x,y);
 95     add(x,y,1);
 96     add(y,x,0);
 97     add(y,x,1);
 98     add(x,y,0);
 99   end;
100   inc(n);
101   sap;
102   writeln(ans);
103 end.
View Code

 

posted on 2014-04-14 15:51  acphile  阅读(48)  评论(0编辑  收藏