点击打开链接
q次询问 每一次加一条边 问加完这条边之后还剩多少割边
可以想到 对于一个无向图 缩完点之后就是一棵树 且树上的边就是原图中的割边
对于每一次加边操作 如果两点不在一个连通分量之中 就会把两点之间的所有割边全部去掉 形成有一个新的连通分量 相当于修改新树图中的一条链 这个过程用树链剖分维护一下就好了
#include
#include
#include
using namespace std;
struct node1
{
int v;
int next;
int flag;
};
struct node2
{
int l;
int r;
int laz;
int val;
};
node1 edge1[400010],edge2[400010];
node2 tree[400010];
int first1[100010],first2[100010],dfn[100010],low[100010],belong[100010],degree[100010];
int pre[100010],fa[100010],deep[100010],sum[100010],son[100010],top[100010],mp1[100010],mp2[100010],mp3[100010];
int n,m,num,cnt,ans;
void addedge(node1* edge,int* first,int u,int v)
{
edge[num].v=v;
edge[num].next=first[u];
edge[num].flag=0;
first[u]=num++;
return;
}
void dfsI(int cur,int pre)
{
int tmp,i,v;
num++;
dfn[cur]=num,low[cur]=num;
tmp=0;
for(i=first1[cur];i!=-1;i=edge1[i].next)
{
v=edge1[i].v;
if(dfn[v]==0)
{
dfsI(v,cur);
low[cur]=min(low[cur],low[v]);
if(low[v]>dfn[cur])
{
edge1[i].flag=1;
edge1[i^1].flag=1;
}
}
else if(v==pre)
{
if(tmp>0) low[cur]=min(low[cur],dfn[v]);
tmp++;
}
else
{
low[cur]=min(low[cur],dfn[v]);
}
}
return;
}
void dfsII(int cur)
{
int i,v;
for(i=first1[cur];i!=-1;i=edge1[i].next)
{
v=edge1[i].v;
if(!belong[v]&&!edge1[i].flag)
{
belong[v]=cnt;
dfsII(v);
}
}
return;
}
void tarjan()
{
int i,u,v;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
num=0,ans=0;
for(u=1;u<=n;u++)
{
if(!dfn[u])
{
dfsI(u,-1);
}
}
memset(belong,0,sizeof(belong));
cnt=0;
for(u=1;u<=n;u++)
{
if(!belong[u])
{
cnt++;
belong[u]=cnt;
dfsII(u);
}
}
/*
printf("***%d***\n",cnt);
for(i=1;i<=n;i++)
{
printf("%d ",belong[i]);
}
printf("\n");
*/
ans=cnt-1;
memset(first2,-1,sizeof(first2));
num=0;
for(u=1;u<=n;u++)
{
for(i=first1[u];i!=-1;i=edge1[i].next)
{
v=edge1[i].v;
if(belong[u]!=belong[v])
{
addedge(edge2,first2,belong[u],belong[v]);
}
}
}
return;
}
void dfsIII(int cur)
{
int i,v,w;
sum[cur]=1,son[cur]=-1;
for(i=first2[cur];i!=-1;i=edge2[i].next)
{
v=edge2[i].v;
if(v!=fa[cur])
{
pre[v]=1,fa[v]=cur,deep[v]=deep[cur]+1;
mp3[i/2+1]=v;
dfsIII(v);
sum[cur]+=sum[v];
if(son[cur]==-1||sum[son[cur]]=tree[2*cur+1].l) res+=query(pl,pr,2*cur+1);
return res;
}
void update(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].val=0;
tree[cur].laz=1;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) update(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) update(pl,pr,2*cur+1);
pushup(cur);
return;
}
int ask(int u,int v)
{
int res;
res=0;
while(top[u]!=top[v])
{
if(deep[top[u]]