题目链接:https://vjudge.net/problem/POJ-3694

题目:给定一个连通图,求桥的个数,每次查询,加入一条边,问加入这条边后还有多少个桥。

思路:tarjan + 并查集 + lca(朴素)

先用tarjan缩点(成环缩点),并存下桥,把每个scc都存下一个源点(源点(boss):以这个点代表这个scc)。

用存下的桥,用并查集重新建图,为了方便之后的操作,并查集建立一颗树,dfn小的在上,dfn大的在下。

lca,用每个点的boss的dfn去跑lca,因为我们建树的方法,总会遇到公共的dfn祖先,把这些点都存下,

最后把这些boss点的dfn都变成祖先的dfn值,这样优化了重复的lca,之后输出答案即可。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <vector>
  5. using namespace std;
  6. #define pb push_back
  7.  
  8. const int N = (int)5e5+;
  9. int n,m,tot,tim,top,scc,ans;//点,边,链式前向星,时间戳,栈,连通数
  10. int head[N],dfn[N],low[N],scc_no[N],s[N],fa[N],boss[N];
  11. //链式前向星,dfn,low,联通块编号,栈,父节点,源点
  12. struct node{
  13. int to;
  14. int nxt;
  15. }e[N << ];
  16. struct _cut{
  17. int x,y;
  18. };
  19. vector<_cut> cut;//桥
  20. vector<int> poi;//lca
  21.  
  22. void init(){
  23. for(int i = ; i <= n; ++i){
  24. head[i] = -;
  25. dfn[i] = ;
  26. }
  27. cut.clear();
  28. scc = tim = tot = ;
  29. }
  30.  
  31. inline void add(int u,int v){
  32. e[tot].to = v;
  33. e[tot].nxt = head[u];
  34. head[u] = tot++;
  35. }
  36.  
  37. void tarjan(int now,int pre){
  38. dfn[now] = low[now] = ++tim;
  39. s[top++] = now;
  40.  
  41. int to,pre_cnt = ;
  42. for(int o = head[now]; ~o; o = e[o].nxt){
  43. to = e[o].to;
  44. if(to == pre && pre_cnt == ) { pre_cnt = ; continue; }
  45. if(!dfn[to]){
  46. tarjan(to,now);
  47. low[now] = min(low[now],low[to]);
  48. if(dfn[now] < low[to]) cut.pb(_cut{now,to});
  49. }
  50. else if(low[now] > dfn[to]) low[now] = dfn[to];
  51. }
  52.  
  53. if(dfn[now] == low[now]){
  54. int p;
  55. ++scc;
  56. fa[now] = now; boss[scc] = now;//记录该scc的源点
  57. do{
  58. p = s[--top];
  59. scc_no[p] = scc;
  60. }while(now != p);
  61. }
  62. }
  63. //得到源点函数
  64. inline int _boss(int x){
  65. return boss[scc_no[x]];
  66. }
  67. //重建图 boss进行并查集
  68. void rebuild(){
  69. ans = cut.size();
  70. int x,y;
  71. for(int i = ; i < ans; ++i){
  72. x = _boss(cut[i].x);
  73. y = _boss(cut[i].y);
  74. //dfn上小,下大的树
  75. if(dfn[x] > dfn[y]) swap(x,y);
  76. fa[y] = x;
  77. }
  78. }
  79.  
  80. void lca(int x,int y){
  81. int fax = _boss(x);
  82. int fay = _boss(y);
  83. if(dfn[fax] == dfn[y]) return;
  84.  
  85. poi.pb(fax); poi.pb(fay);
  86. while(dfn[fax] != dfn[fay]){
  87. while(dfn[fax] > dfn[fay]){
  88. --ans;
  89. fax = fa[fax];
  90. poi.pb(fax);
  91. }
  92. while(dfn[fax] < dfn[fay]){
  93. --ans;
  94. fay = fa[fay];
  95. poi.pb(fay);
  96. }
  97. }
  98.  
  99. int n = poi.size();//所有boss点dfn改变为祖先的dfn
  100. for(int i = ; i < n; ++i) dfn[poi[i]] = dfn[fax];
  101. poi.clear();
  102. }
  103.  
  104. int main(){
  105.  
  106. int _case = ;
  107. while(~scanf("%d%d",&n,&m) && (n+m)){
  108. init();
  109. int u,v;
  110. for(int i = ; i < m; ++i){
  111. scanf("%d%d",&u,&v);
  112. add(u,v); add(v,u);
  113. }
  114.  
  115. tarjan(,);
  116. rebuild();
  117.  
  118. int q;
  119. scanf("%d",&q);
  120. printf("Case %d:\n",++_case);
  121. while(q--){
  122. scanf("%d%d",&u,&v);
  123. lca(u,v);
  124. printf("%d\n",ans);
  125. }
  126. }
  127.  
  128. return ;
  129. }

kuangbin专题 专题九 连通图 POJ 3694 Network的更多相关文章

  1. kuangbin专题 专题九 连通图 POJ 1236 Network of Schools

    题目链接:https://vjudge.net/problem/POJ-1236 题目:有向图,有若干个连通图,点之间有单向边边就可以单向传递信息,问: (1)至少需要发送几份信息才能使得每个点都传递 ...

  2. Poj 3694 Network (连通图缩点+LCA+并查集)

    题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条 ...

  3. POJ 3694——Network——————【连通图,LCA求桥】

    Network Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  4. kuangbin专题 专题九 连通图 POJ 3177 Redundant Paths

    题目链接:https://vjudge.net/article/371?tdsourcetag=s_pcqq_aiomsg 题目:给定一个连通图,题目说,任意两个点至少有一条路线可以相互到达, 为保证 ...

  5. poj 3694 Network 边双连通+LCA

    题目链接:http://poj.org/problem?id=3694 题意:n个点,m条边,给你一个连通图,然后有Q次操作,每次加入一条边(A,B),加入边后,问当前还有多少桥,输出桥的个数. 解题 ...

  6. [双连通分量] POJ 3694 Network

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9434   Accepted: 3511 Descripti ...

  7. POJ 3694 Network (tarjan + LCA)

    题目链接:http://poj.org/problem?id=3694 题意是给你一个无向图n个点,m条边,将m条边连接起来之后形成一个图,有Q个询问,问将u和v连接起来后图中还有多少个桥. 首先用t ...

  8. poj 3694 Network(双连通分量)

    题目:http://poj.org/problem?id=3694 #include <iostream> #include <cstring> #include <cs ...

  9. poj 3694 Network(割边+lca)

    题目链接:http://poj.org/problem?id=3694 题意:一个无向图中本来有若干条桥,有Q个操作,每次加一条边(u,v),每次操作后输出桥的数目. 分析:通常的做法是:先求出该无向 ...

随机推荐

  1. Adam那么棒,为什么还对SGD念念不忘 (1) —— 一个框架看懂优化算法

    机器学习界有一群炼丹师,他们每天的日常是: 拿来药材(数据),架起八卦炉(模型),点着六味真火(优化算法),就摇着蒲扇等着丹药出炉了. 不过,当过厨子的都知道,同样的食材,同样的菜谱,但火候不一样了, ...

  2. 2007年NOIP普及组复赛题解

    题目涉及算法: 奖学金:结构体排序: 纪念品分组:贪心: 守望者的逃离:动态规划: Hanoi 双塔问题:递推. 奖学金 题目链接:https://www.luogu.org/problem/P109 ...

  3. java 集合之Arraylist的遍历及排序

    最近培训是先学习java基础 从最基本的开始学起 因为今天刚刚开博客 要把上周的一些重点内容归纳一下 1.Arraylist常用遍历以及排序 import java.util.ArrayList; i ...

  4. Codeforces Round #186 (Div. 2)

    A. Ilya and Bank Account 模拟. B. Ilya and Queries 前缀和. C. Ilya and Matrix 考虑每个元素的贡献. 边长为\(2^n\)时,贡献为最 ...

  5. H3C 单路径网络中环路产生过程(3)

  6. P1067 叠罗汉

    题目描述 茜茜和聪聪是关系很好的同桌,有一天,茜茜觉得天空中的白云像棉花糖一样,应该很好吃吧,但是够不着,她很烦恼. 聪聪为了帮助茜茜解决烦恼,决定帮他把天空中的白云摘下来做成棉花糖给她吃. 但是聪聪 ...

  7. P1020 从大到小排序

    题目描述 给你n个整数,请你按照从大到小的顺序输出它们. 输入格式 输入的第一行包含一个整数 \(n(1 \le n \le 10^3)\) ,用于表示元素的个数. 输入的第二行包含 \(n\) 个整 ...

  8. keep-alive及路由渲染

    切换路由的时候,每次切换的时候得重新渲染一遍,这样的话会影响到性能的.此时用<keep-alive>包裹着app里的<router-view>,进行缓存. 如果一个页面涉及到了 ...

  9. linux 搭建jenkins

    一.什么是持续集成? (1)Continuous integration(CI) 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员至少集成一次,也就意味着每天可能会发生多次集 ...

  10. 查看虚拟机里的Centos7的IP(设置centos网卡)

    这里之所以是查看下IP ,是我们后面要建一个Centos远程工具Xshell 连接Centos的时候,需要IP地址,所以我们这里先 学会查看虚拟机里的Centos7的IP地址 首先我们登录操作系统 用 ...