刚开始看错题了,以为询问的边会一直保留,然后想得超复杂,最后弃掉了。
明白真正题意后才发现这只是一道基础题目,读懂题目后转化模型:现在有N个点,有M条无向边,图中已有若干点能互相到达,且路径至少为两条,也就是这对点在同一个双连通分量中,然后询问新增的点,最后输出所有结果的和。很明显就是用tarjan进行缩点,然后就成了一棵树,在树上求答案。
容易看出缩点后无向图成为一棵树。增加一条边将产生一个环。设环上有 k 个点,第 i 个点的点权为 vi。经过简单的计算可以得到增加的安全点对数为。在树上倍增计算就可以了!
const mx=100000;
var
next,data:array[0..8*mx] of longint;
last,a,dfn,low,dis,zh:array[0..2*mx] of longint;
f,u,v:array[0..2*mx,0..25] of longint;
p1,p2:array[0..4*mx] of boolean;
x,y:array[0..4*mx] of longint;
n,m,q,i,j,sum,num:longint;
ans,tot,s:int64;
function min(x,y:longint):longint;
begin
if xthen exit(x) else exit(y);
end;
procedure ins(x,y:longint);
begin
inc(sum);
data[sum]:=y;
next[sum]:=last[x];
last[x]:=sum;
end;
procedure tarjan(x:longint);
var i:longint;
begin
inc(zh[0]);zh[zh[0]]:=x;
p2[x]:=true;
inc(sum);
dfn[x]:=sum;low[x]:=sum;
i:=last[x];
while i<>0 do
begin
if p1[(i+1) div 2]=false then
if dfn[data[i]]<>0 then
begin
if p2[data[i]] then low[x]:=min(low[x],low[data[i]]);
end
else
begin
p1[(i+1) div 2]:=true;
tarjan(data[i]);
low[x]:=min(low[x],low[data[i]]);
end;
i:=next[i];
end;
if dfn[x]=low[x] then
begin
inc(num);
while dfn[zh[zh[0]]]<>low[zh[zh[0]]] do
begin
dis[zh[zh[0]]]:=num;
p2[zh[zh[0]]]:=false;
dec(zh[0]);
end;
dis[zh[zh[0]]]:=num;
p2[zh[zh[0]]]:=false;
dec(zh[0]);
end;
end;
procedure dfs(x,fa,deep:longint);
var i,j:longint;
begin
f[x,0]:=fa;u[x,0]:=a[fa];v[x,0]:=sqr(a[fa]);zh[x]:=deep;
i:=1;
while f[f[x,i-1],i-1]<>0 do
begin
f[x,i]:=f[f[x,i-1],i-1];
u[x,i]:=u[f[x,i-1],i-1]+u[x,i-1];
v[x,i]:=v[f[x,i-1],i-1]+v[x,i-1];
inc(i);
end;
i:=last[x];
while i<>0 do
begin
if p1[(i+1) div 2]=false then
begin
p1[(i+1) div 2]:=true;
dfs(data[i],x,deep+1);
end;
i:=next[i];
end;
end;
procedure rebuild;
var i:longint;
begin
sum:=0;
for i:=1 to n do inc(a[dis[i]]);
fillchar(last,sizeof(last),0);
fillchar(next,sizeof(next),0);
fillchar(data,sizeof(data),0);
for i:=1 to m do
if dis[x[i]]<>dis[y[i]] then
begin
ins(dis[x[i]],dis[y[i]]);ins(dis[y[i]],dis[x[i]]);
end;
end;
function up(x,deep:longint):longint;
var i:longint;
begin
while zh[x]>deep do
begin
i:=0;
while (f[x,i+1]<>0)and(zh[f[x,i+1]]>deep) do inc(i);
ans:=ans+u[x,i];tot:=tot+v[x,i];
x:=f[x,i];
end;
exit(x);
end;
procedure jump(x,y:longint);
var i:longint;
begin
if x<>y then
begin
ans:=ans+a[y];tot:=tot+sqr(a[y]);
end else exit;
while x<>y do
begin
i:=0;
while (f[x,i+1]<>0)and(f[y,i+1]<>0)and(f[x,i+1]<>f[y,i+1]) do inc(i);
ans:=ans+u[x,i]+u[y,i];
tot:=tot+v[x,i]+v[y,i];
x:=f[x,i];y:=f[y,i];
end;
ans:=ans-a[x];tot:=tot-sqr(a[x]);
end;
begin
readln(n,m,q);
for i:=1 to m do
begin
readln(x[i],y[i]);
ins(x[i],y[i]);ins(y[i],x[i]);
end;
sum:=0;
for i:=1 to n do
if dfn[i]=0 then tarjan(i);
rebuild;
fillchar(p1,sizeof(p1),0);
dfs(1,0,1);
for i:=1 to q do
begin
readln(x[0],y[0]);
x[0]:=dis[x[0]];y[0]:=dis[y[0]];
if zh[x[0]]0]] then
begin
num:=x[0];x[0]:=y[0];y[0]:=num;
end;
ans:=a[x[0]];tot:=sqr(a[x[0]]);
x[0]:=up(x[0],zh[y[0]]);
jump(x[0],y[0]);
s:=s+ans*ans-tot;
end;
writeln(s);
end.