题意:

给定一个n个点m条边的无向图,q个操作,每个操作给(x,y)连边并询问此时图中的割边有多少条。(连上的边会一直存在)

n<=1e5,m<=2*10^5,q<=1e3,多组数据。

题解:

用tarjan求边双连通分量并缩点,缩点后组成一棵树,记录此时割边共有sum条。

连接(x,y),设c[i]为缩点后i所在的新点(边双连通分量),则c[x]-->lca-->c[y]形成一个环,环上的所有边都不再是割边,走一遍并标记,如果遇到没标记过的就sum--。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; const int N=,M=,K=;
int n,m,al,bl,sum,num,sl,cnt;
int afirst[N],bfirst[N],fa[N][K],dfn[N],low[N],is[N],c[N],s[N],dep[N];
struct node{
int x,y,tmp,next;
}a[*M],b[*M]; int minn(int x,int y){return x<y ? x:y;} void ins_a(int x,int y)
{
a[++al].x=x;a[al].y=y;a[al].tmp=;
a[al].next=afirst[x];afirst[x]=al;
} void ins_b(int x,int y)
{
b[++bl].x=x;b[bl].y=y;
b[bl].next=bfirst[x];bfirst[x]=bl;
} void tarjan(int x)
{
dfn[x]=low[x]=++num;
s[++sl]=x;
for(int i=afirst[x];i;i=a[i].next)
{
if(a[i].tmp) continue;
a[i].tmp=;
a[i%== ? i-:i+].tmp=;
int y=a[i].y;
if(!dfn[y])
{
tarjan(y);
low[x]=minn(low[x],low[y]);
if(dfn[x]<low[y])
{
sum++;//printf("%d -- > %d\n",x,y);
cnt++;
int z;
while()
{
z=s[sl--];
c[z]=cnt;
if(z==y) break;
}
}
}
else low[x]=minn(low[x],dfn[y]);
}
} void dfs(int x)
{
for(int i=bfirst[x];i;i=b[i].next)
{
int y=b[i].y;
if(y==fa[x][]) continue;
fa[y][]=x;dep[y]=dep[x]+;
dfs(y);
}
} void prepare_lca()
{
memset(fa,,sizeof(fa));
memset(dep,,sizeof(dep));
memset(is,,sizeof(is));
dep[]=;
dfs();
for(int j=;j<=;j++)
for(int i=;i<=n;i++)
fa[i][j]=fa[fa[i][j-]][j-];
} int get_lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=;i>=;i--)
if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=;i>=;i--)
{
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
}
return fa[x][];
} void del(int x,int y,int lca)
{
while(x!=lca)
{
if(!is[x]) sum--;
is[x]=;
x=fa[x][];
}
while(y!=lca)
{
if(!is[y]) sum--;
is[y]=;
y=fa[y][];
}
} int main()
{
freopen("a.in","r",stdin);
int q,x,y,T=;
while()
{
scanf("%d%d",&n,&m);
if(!n && !m) return ;
printf("Case %d:\n",++T);
al=;bl=;sum=;
memset(afirst,,sizeof(afirst));
memset(bfirst,,sizeof(bfirst));
num=;sl=;cnt=;
memset(dfn,,sizeof(dfn));
memset(c,,sizeof(c));
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
ins_a(x,y);ins_a(y,x);
}
for(int i=;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
if(sl)
{
cnt++;
for(int i=;i<=sl;i++) c[s[i]]=cnt;
sl=;
}
}
} for(int i=;i<=*m;i++)
{
x=a[i].x,y=a[i].y;
if(c[x]!=c[y]) ins_b(c[x],c[y]);
}
// for(int i=1;i<=bl;i++)
// printf("%d -- > %d\n",b[i].x,b[i].y);
// for(int i=1;i<=n;i++) printf("c [ %d ] = %d\n",i,c[i]);
prepare_lca();
scanf("%d",&q);
for(int i=;i<=q;i++)
{
scanf("%d%d",&x,&y);
x=c[x];y=c[y];
int lca=get_lca(x,y);
del(x,y,lca);
printf("%d\n",sum);
}
printf("\n");
}
return ;
}

最新文章

  1. item2快捷键
  2. .Net中Remoting通信机制
  3. mysql 的 VARCHAR VARCHAR2
  4. TCP的连接控制
  5. C#数组全解
  6. open-falcon 安装
  7. 项目总结(四)--- 网络封包分析工具Charles
  8. DWZ中关于iframeCallback和validateCallback的注意事项
  9. 1029 C语言文法
  10. Android SDK Manager更新报错
  11. input 中的enabled与disabled属性
  12. Spark Streaming揭秘 Day33 checkpoint的使用
  13. STM32的FSMC总线驱动ili9341,掉电重启无法正常显示的问题
  14. linux内核学习之四:进程切换简述
  15. HTML5的兼容问题以及调用js文件的方法
  16. apache和nginx支持SSI配置
  17. js创建、写入、读取文件(转)
  18. centos java tomcat 中文乱码解决办法
  19. springboot学习章节代码-Spring MVC基础
  20. C++编译器详解(一)

热门文章

  1. 什么是BCL
  2. DNS域名解析协议
  3. LintCode-88.最近公共祖先
  4. python学习第二天-基本数据类型常用方法
  5. &lt;Effective C++&gt;读书摘要--Implementations&lt;一&gt;
  6. css那些事儿4 背景图像
  7. vue中使用monaco-editor打包文件混乱的问题
  8. 从实战角度浅析snmp
  9. FullCalendar(日程管理控件)
  10. ictclas4j 分词工具包 安装流程