题意:给定一个n个点m个无向联通图,再给出一条边,最少删除多少条边使得这条边既出现在最小生成树上又出现在最大生成树上
...说实话,这数据范围有点吓人,瞬间不知所措...._(:3 」∠)_ .
对于某一条边,如果边权小于它的边能使其两个端点连通,则这条边一定不会出现在最小生成树中。
对于某一条边,如果边权大于它的边能使其两个端点连通,则这条边一定不会出现在最大生成树中。
所以,
原题可变成:删去最少的边,使小于新边边权的边不能使两端点连通、大于该边权的边也不能使两端点连通。
妥妥的最小割....
先把所有小于新边边长的边,设边权为1建图来一遍最小割
再把所有大于新边边长的边,设边权为1建图来一遍最小割
这样最小割即为要删去的边的条数,对两次结果取和即为最终答案
注意重建图之前的清零...
据说,dinic对于容量为1的网络时间复杂度为O(min(N^(2/3),M^(1/2))*M),还是可以的..._(:3 」∠)_
type
rec=record
a,b,len:longint;
end;
{$ inline on}
var
n,m,ll,x,y,z :longint;
ss,st,tt,ans :longint;
l :array[0..200010] of rec;
last,que,dis :array[0..20010] of longint;
len,other,pre :array[0..400010] of longint;
i :longint;
function min(a,b:longint):longint;inline;
begin
if a<b then exit(a) else exit(b);
end;
procedure connect(x,y,z:longint);inline;
begin
inc(ll);
pre[ll]:=last[x];
last[x]:=ll;
other[ll]:=y;
len[ll]:=z;
end;
procedure sort(ll,rr:longint);
var
i,j,x:longint;
y:rec;
begin
i:=ll; j:=rr; x:=l[(ll+rr)>>1].len;
while (i<=j) do
begin
while l[i].len<x do inc(i);
while l[j].len>x do dec(j);
if (i<=j) then
begin
y:=l[i]; l[i]:=l[j]; l[j]:=y;
inc(i); dec(j);
end;
end;
if i<rr then sort(i,rr);
if j>ll then sort(ll,j);
end;
function bfs:boolean; inline;
var
p,q,cur,h,tl:longint;
begin
fillchar(dis,sizeof(dis),0);
h:=0; tl:=1; que[1]:=ss; dis[ss]:=1;
while (h<>tl) do
begin
h:=h mod 20005+1;
cur:=que[h];
q:=last[cur];
while (q<>0) do
begin
p:=other[q];
if (dis[p]=0) and (len[q]>0) then
begin
dis[p]:=dis[cur]+1;
tl:=tl mod 20005+1;
que[tl]:=p;
if p=st then exit(true);
end;
q:=pre[q];
end;
end;
exit(false);
end;
function dinic(x,flow:longint):longint;
var
rest,tt,p,q:longint;
begin
if x=st then exit(flow);
rest:=flow;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if (dis[p]=dis[x]+1) and (len[q]>0) and (rest>0) then
begin
tt:=dinic(p,min(rest,len[q]));
dec(len[q],tt);
inc(len[q xor 1],tt);
dec(rest,tt);
if rest=0 then exit(flow);
end;
q:=pre[q];
end;
if rest=flow then dis[x]:=0;
exit(flow-rest);
end;
begin
read(n,m);
for i:=1 to m do read(l[i].a,l[i].b,l[i].len);
read(ss,st,tt);
sort(1,m);
ll:=1; ans:=0;
for i:=1 to m do
if l[i].len<tt then
begin
connect(l[i].a,l[i].b,1);
connect(l[i].b,l[i].a,1);
end else break;
while bfs do inc(ans,dinic(ss,maxlongint div 10));
ll:=1;
fillchar(last,sizeof(last),0);
for i:=m downto 1 do
if l[i].len>tt then
begin
connect(l[i].a,l[i].b,1);
connect(l[i].b,l[i].a,1);
end else break;
while bfs do inc(ans,dinic(ss,maxlongint div 10));
writeln(ans);
end.
——by Eirlys