[BZOJ]2561 最小生成树 最小割

为什么删除最少的边判连通连最小割都没想到。。。估计是废了。。。
考虑Kruskal的过程(最小生成树)如果有一条边(u,v),若所有比他小的边能使u,v联通,这条边就不必加入生成树中,最大生成树也同理。于是我们只要把权值比L小的调出来跑最小割,权值比L大的也挑出来跑最小割。两个加一下就是答案了。

代码:

type
  edge=^edgenode;
  edgenode=record
    t,c,f:longint;
    next,rev:edge;
  end;
const maxl=1000000000;
var
  n,m,i,s,t,len,ans:longint;
  e:array[0..200100,0..2]of longint;
  con:array[0..20010,0..1]of edge;
  visit:array[0..20010]of boolean;
  ne,dl:array[0..20010]of longint;
procedure ins(x,y,b:longint);
var
  p:edge;
begin
  new(p);
  p^.t:=y;
  p^.c:=1;
  p^.f:=0;
  p^.next:=con[x,b];
  con[x,b]:=p;
  new(p);
  p^.t:=x;
  p^.c:=0;
  p^.f:=0;
  p^.next:=con[y,b];
  con[y,b]:=p;
  con[x,b]^.rev:=con[y,b];
  con[y,b]^.rev:=con[x,b];
end;
function min(x,y:longint):longint;
begin
  if x>y then exit(y)
  else exit(x);
end;

function bfs(b:longint):boolean;
var
  p:edge;
  head,tail:longint;
begin
  head:=1;
  tail:=1;
  dl[1]:=s;
  ne[s]:=1;
  bfs:=false;
  while head<=tail do
  begin
    p:=con[dl[head],b];
    if dl[head]=t then bfs:=true;
    while p<>nil do
    begin
      if (ne[p^.t]=0)and(p^.c>p^.f) then
      begin
        ne[p^.t]:=ne[dl[head]]+1;
        inc(tail);
        dl[tail]:=p^.t;
      end;
      p:=p^.next;
    end;
    inc(head);
  end;
end;
function dinic(k,flow,b:longint):longint;
var
  p:edge;
  o:longint;
begin
  if k=t then exit(flow);
  if visit[k]=true then exit(0);
  dinic:=0;
  p:=con[k,b];
  while p<>nil do
  begin
    if (ne[p^.t]=ne[k]+1)and(p^.c>p^.f) then
    begin
      o:=dinic(p^.t,min(flow,p^.c-p^.f),b);
      dinic:=dinic+o;
      inc(p^.f,o);
      dec(p^.rev^.f,o);
      dec(flow,o);
      if flow=0 then break;
    end;
    p:=p^.next;
  end;
  if dinic=0 then visit[k]:=true;
end;
begin
  readln(n,m);
  for i:=1 to m do
    readln(e[i,0],e[i,1],e[i,2]);
  readln(s,t,len);
  for i:=1 to m do
  begin
    if e[i,2]<len then begin ins(e[i,0],e[i,1],0); ins(e[i,1],e[i,0],0); end;
    if e[i,2]>len then begin ins(e[i,0],e[i,1],1); ins(e[i,1],e[i,0],1); end;
  end;
  ans:=0;
  while bfs(0) do
  begin
    fillchar(visit,sizeof(visit),false);
    ans:=ans+dinic(s,maxl,0);
    fillchar(ne,sizeof(ne),0);
  end;
  fillchar(ne,sizeof(ne),0);
  while bfs(1) do
  begin
    fillchar(visit,sizeof(visit),false);
    ans:=ans+dinic(s,maxl,1);
    fillchar(ne,sizeof(ne),0);
  end;
  writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值