题意:一个无向图可以有重边,下面q个操作,每次在两个点间连接一条有向边,每次连接后整个无向图还剩下多少桥
分析:先跑一边tarjan把所有的桥边求出来,同时建好深搜树。没加入一条边也就是说在树上这两个点之间的路径和该边构成一个环,也就是这两点的路径上的边都不是桥边了,那么就跑一边双循环爆推LCA把这些边删掉就好了。
代码:
var e,tot,t,n,m,step:longint; side:array[1..1000000] of record x,y,next:longint; end; dfn,low,f,last:array[1..100000] of longint; v:array[1..100000] of boolean; procedure add(x,y:longint); begin inc(e); side[e].x:=x; side[e].y:=y; side[e].next:=last[x]; last[x]:=e; inc(e); side[e].x:=y; side[e].y:=x; side[e].next:=last[y]; last[y]:=e; end; procedure init; var i,x,y:longint; begin e:=0; fillchar(last,sizeof(last),0); for i:=1 to m do begin readln(x,y); add(x,y); end; end; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure tarjan(x,fa:longint); var i:longint; begin inc(t); dfn[x]:=t; low[x]:=t; i:=last[x]; while i>0 do with side[i] do begin if y<>fa then if dfn[y]=0 then begin f[y]:=i; tarjan(y,x); if low[y]>dfn[x] then begin inc(tot); v[y]:=true; end; low[x]:=min(low[y],low[x]); end else low[x]:=min(dfn[y],low[x]); i:=next; end; end; procedure lca(x,y:longint); begin if dfn[x]<dfn[y] then begin x:=x xor y; y:=x xor y; x:=x xor y; end; while dfn[x]>dfn[y] do begin if v[x] then begin dec(tot); v[x]:=false; end; x:=side[f[x]].x; end; while y<>x do begin if v[y] then begin dec(tot); v[y]:=false; end; y:=side[f[y]].x; end; end; procedure main; var i,q,x,y:longint; begin fillchar(dfn,sizeof(dfn),0); fillchar(low,sizeof(low),0); fillchar(v,sizeof(v),false); t:=0; tot:=0; for i:=1 to n do if dfn[i]=0 then tarjan(i,0); readln(q); for i:=1 to q do begin readln(x,y); lca(x,y); writeln(tot); end; end; begin readln(n,m); while not eof do begin init; inc(step); writeln('Case ',step,':'); main; writeln; readln(n,m); end; end.