最小割的经典模型,体现出最小割的基本定义,把两个集合划分的最小代价
把一开始同意的人连源点,不同意的连汇点,有关系的人之间连边,流量都为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.