题目大意
给出一个图,一些询问加入一条边后增加多少对双连通点对(u,v)(v,u)算两对。
解题思路
tarjan后建树,答案即为(u,v)路径上size和的平方减去平方和,倍增即可。
code
using namespace std;
int const maxn=200000,maxm=400000,inf=2147483647;
int n,m,q,lo,time,top,gra=2,to[maxm*2+10],next[maxm*2+10],begin[maxn+10],dfn[maxn+10],
low[maxn+10],inst[maxn+10],st[maxn+10],bel[maxn+10],fat[maxn+10][20],
dep[maxn+10],two[maxn+10],x[maxn*2+10],y[maxn*2+10];
LL sx[maxn+10][20],sxx[maxn+10][20],size[maxn+10];
void insert(int u,int v){
to[gra]=v;
next[gra]=begin[u];
begin[u]=gra++;
to[gra]=u;
next[gra]=begin[v];
begin[v]=gra++;
}
void tarjan(int now,int pre){
dfn[now]=low[now]=++time;
inst[st[++top]=now]=1;
for(int i=begin[now];i;i=next[i])
if(i!=(pre^1)){
if(!dfn[to[i]]){
tarjan(to[i],i);
low[now]=min(low[now],low[to[i]]);
}else if(inst[to[i]])low[now]=min(low[now],dfn[to[i]]);
}
if(dfn[now]==low[now]){
for(;st[top]!=now;bel[st[top]]=now,size[now]++,inst[st[top--]]=0);
bel[st[top]]=now,size[now]++,inst[st[top--]]=0;
}
}
LL lc(int u,int v){
if(dep[u]<dep[v])swap(u,v);
LL ax=0,axx=0;
fd(i,lo,0)
if(dep[fat[u][i]]>=dep[v])
ax+=sx[u][i],
axx+=sxx[u][i],
u=fat[u][i];
if(u==v)return (ax+sx[u][0])*(ax+sx[u][0])-(axx+sxx[u][0]);
fd(i,lo,0)
if(fat[u][i]!=fat[v][i])
ax+=sx[u][i]+sx[v][i],
axx+=sxx[u][i]+sxx[v][i],
u=fat[u][i],
v=fat[v][i];
ax+=sx[fat[u][0]][0]+sx[u][0]+sx[v][0];
axx+=sxx[fat[u][0]][0]+sxx[u][0]+sxx[v][0];
return ax*ax-axx;
}
int read(){
int v=0;char ch=getchar();
for(;(ch<'0')||(ch>'9');ch=getchar());
for(;(ch>='0')&&(ch<='9');v=v*10+ch-'0',ch=getchar());
return v;
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
n=read();m=read();q=read();
fo(i,1,m){
x[i]=read();y[i]=read();
insert(x[i],y[i]);
}
fo(i,1,n)
if(!dfn[i])tarjan(i,0);
fo(i,1,n)sx[i][0]=size[bel[i]],sxx[i][0]=size[bel[i]]*size[bel[i]];
lo=log(n)/log(2);
fo(i,1,m)
if(bel[x[i]]!=bel[y[i]])
fat[bel[y[i]]][0]=bel[x[i]];
fo(i,1,n)if(!fat[i][0])dep[i]=1;
fo(i,1,n)if(fat[i][0])dep[i]=2;
two[0]=1;fo(i,1,lo)two[i]=two[i-1]*2;
fo(j,1,lo)
fo(i,1,n){
sx[i][j]=sx[i][j-1]+sx[fat[i][j-1]][j-1],
sxx[i][j]=sxx[i][j-1]+sxx[fat[i][j-1]][j-1],
fat[i][j]=fat[fat[i][j-1]][j-1];
if(fat[i][j])dep[i]=dep[fat[i][j]]+two[j];
}
LL ans=0;
fo(i,1,q){
int x=read(),y=read();
if(bel[x]!=bel[y])ans+=lc(bel[x],bel[y]);
}
printf("%lld",ans);
return 0;
}