记得有个梗那一天,zw学生zzh大佬说逃不掉的路变成a不掉的题哈哈哈哈;

分离的路径:

BZOJ 1718
POJ 3177
LUOGU 286

思路:在同一个边双连通分量中,任意两点都有至少两条独立路可达,所以同一个边双连通分量里的所有点可以看做同一个点。缩点后,新图是一棵树,树的边就是原无向图的桥。

现在问题转化为:在树中至少添加多少条边能使图变为双连通图。
结论:添加边数=(树中度为1的节点数+1)/2;

具体方法为,首先把两个最近公共祖先最远的两个叶节点之间连接一条边,这样可以把这两个点到祖先的路径上所有点收缩到一起,因为一个形成的环一定是双连通的。
然后再找两个最近公共祖先最远的两个叶节点,这样一对一对找完,恰好是(leaf+1)/2次,把所有点收缩到了一起。

点评:
边双连通分量缩点后,原图变成一颗真正的树,而树上各种操作可以和其他知识点结合起来。
这种敏感性要有,比如缩点之后就可以快速求必经边,必经点之类的。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=3e5+;
  4. template<typename T>inline void read(T &x)
  5. {
  6. x=;
  7. T f=,ch=getchar();
  8. while (!isdigit(ch)) ch=getchar();
  9. if (ch=='-') f=-, ch=getchar();
  10. while (isdigit(ch)) x=(x<<)+(x<<)+(ch^), ch=getchar();
  11. x*=f;
  12. }
  13. int ver[maxn<<],Next[maxn<<],head[maxn],len=;
  14. inline void add(int x,int y)
  15. {
  16. ver[++len]=y,Next[len]=head[x],head[x]=len;
  17. }
  18. int dfn[maxn],low[maxn],id;
  19. bool bridge[maxn<<];
  20. inline void tarjan(int x,int inedge)
  21. {
  22. dfn[x]=low[x]=++id;
  23. for (int i=head[x];i;i=Next[i])
  24. {
  25. int y=ver[i];
  26. if (!dfn[y])
  27. {
  28. tarjan(y,i);
  29. low[x]=min(low[x],low[y]);
  30. if (low[y]>dfn[x])
  31. bridge[i]=bridge[i^]=;
  32. }
  33. else if (i!=(inedge^))
  34. low[x]=min(low[x],dfn[y]);
  35. }
  36. }
  37. int c[maxn],Out[maxn],dcc;
  38. inline void dfs(int x)
  39. {
  40. c[x]=dcc;
  41. for (int i=head[x];i;i=Next[i])
  42. {
  43. int y=ver[i];
  44. if (c[y] || bridge[i]) continue;
  45. dfs(y);
  46. }
  47. }
  48. int main()
  49. {
  50. freopen("rpaths.in","r",stdin);
  51. freopen("rpaths.out","w",stdout);
  52. int n,m;read(n);read(m);
  53. for (int i=;i<=m;++i)
  54. {
  55. int x,y;
  56. read(x);read(y);
  57. add(x,y);add(y,x);
  58. }
  59. for (int i=;i<=n;++i)
  60. if (!dfn[i]) tarjan(i,-);
  61. for (int i=;i<=n;++i)
  62. if (!c[i]) ++dcc,dfs(i);
  63. for (int i=;i<=len;i+=)
  64. {
  65. int x=ver[i^],y=ver[i];
  66. if (c[x]!=c[y])
  67. ++Out[c[x]],++Out[c[y]];
  68. }
  69. int ans=;
  70. for (int i=;i<=dcc;++i)
  71. if (Out[i]==) ++ans;
  72. printf("%d\n",(ans+)>>);
  73. return ;
  74. }

第二题:逃不掉的路

题目描述
现代社会,路是必不可少的。任意两个城镇都有路相连,而且往往不止一条。但有些路连年被各种XXOO,走着很不爽。按理说条条大路通罗马,大不了绕行其他路呗——可小撸却发现:从a城到b城不管怎么走,总有一些逃不掉的必经之路。
他想请你计算一下,a到b的所有路径中,有几条路是逃不掉的?
输入格式
第一行是n和m,用空格隔开。
接下来m行,每行两个整数x和y,用空格隔开,表示x城和y城之间有一条长为1的双向路。
第m+2行是q。接下来q行,每行两个整数a和b,用空格隔开,表示一次询问。
输出格式
对于每次询问,输出一个正整数,表示a城到b城必须经过几条路。
样例输入
5 5
1 2
1 3
2 4
3 4
4 5
2
1 4
2 5
样例输出
0
1
样例解释
第1次询问,1到4的路径有 1–2--4 ,还有 1–3--4 。没有逃不掉的道路,所以答案是0。
第2次询问,2到5的路径有 2–4--5 ,还有 2–1--3–4--5 。必须走“4–5”这条路,所以答案是1。
数据约定与范围
共10组数据,每组10分。
有3组数据,n ≤ 100 , n ≤ m ≤ 200 , q ≤ 100。
另有2组数据,n ≤ 103, n ≤ m ≤ 2 x 103 , 100 < q ≤ 105。
另有3组数据,103 < n ≤ 105 , m = n-1 , 100 < q ≤ 105。
另有2组数据,103 < n ≤ 105 , n ≤ m ≤ 2 x 105 , 100 < q ≤ 105。
对于全部的数据,1 ≤ x,y,a,b ≤ n;对于任意的道路,两端的城市编号之差不超过104;
任意两个城镇都有路径相连;同一条道路不会出现两次;道路的起终点不会相同;查询的两个城市不会相同。

分析:既然是求必须经过的边,那么边双包含的集合肯定不是必须经过的,就可以把所有边双缩点;

原图得到一颗树后,问题就变成了简单的求树上两点之间的距离。

这个题就是lca+边双的题啦:

第三题:矿场搭建

BZOJ 2730LUOGU 3225

首先我们知道,对于这张图,我们可以枚举坍塌的是哪个点,对于每个坍塌的点,最多可以将图分成若干个不连通的块,这样每个块我们可能需要一个出口才能满足题目的要求,枚举每个坍塌的点显然是没有意义的,我们只需要每个图的若干个割点,这样除去割点的图有若干个块,我们可以求出只与一个割点相连的块,这些块必须要一个出口才能满足题目的要求,每个块内有块内个数种选法,然后将所有满足一个割点相连的块的点数连乘就行了。

对于每个与一个割点相连的块必须建出口可以换一种方式理解,我们将每个块看做一个点,那么算上割点之后,这张图就变成了一颗树,只有叶子节点我们需要建立出口,因为对于非叶子节点我们不论断掉哪个点我们都有另一种方式相连,这里的叶子节点就是与一个割点相连的块。
最后还有个特判,就是对于一个双连通图,我们至少需要选取两个点作为出口,因为如果就选一个,可能该点为坍塌点,这时我们就任选两个点就行了,方案数为点数x(点数-1)>>1。

代码该如何写?
先tarjan求一下所有的点双。
然后对于每一个点双,分类讨论:
1、只有一个割点,必须选一个非割点。
2、有>=2个割点,不用选
3、有0个割点,必须选俩。
画个图理解一下撒;

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=;
  4. struct gg
  5. {
  6. int y,next;
  7. }a[maxn*maxn];
  8. template<typename T>inline void read(T &x)
  9. {
  10. x=;
  11. T f=,ch=getchar();
  12. while (!isdigit(ch)) ch=getchar();
  13. if (ch=='-') f=-, ch=getchar();
  14. while (isdigit(ch)) x=(x<<)+(x<<)+(ch^), ch=getchar();
  15. x*=f;
  16. }
  17. long long hl,ans=;
  18. int lin[maxn],len;
  19. inline void add(int x,int y)
  20. {
  21. a[++len].y=y;
  22. a[len].next=lin[x];
  23. lin[x]=len;
  24. }
  25. int dfn[maxn],low[maxn],num,root;
  26. bool cut[maxn];
  27. inline void tarjan(int x,int fa)
  28. {
  29. dfn[x]=low[x]=++num;
  30. int flag=;
  31. for (int i=lin[x];i;i=a[i].next)
  32. {
  33. int y=a[i].y;
  34. if (!dfn[y])
  35. {
  36. tarjan(y,x);
  37. low[x]=min(low[x],low[y]);
  38. if(low[y]>=dfn[x])
  39. {
  40. ++flag;
  41. if (x!=root||flag>) cut[x]=;
  42. }
  43. }
  44. else if (y!=fa)
  45. low[x]=min(low[x],dfn[y]);
  46. }
  47. }
  48. int vis[maxn],k,cnt;
  49. inline void dfs(int x)
  50. {
  51. vis[x]=k;
  52. ++cnt;
  53. for(int i=lin[x];i;i=a[i].next)
  54. {
  55. int y=a[i].y;
  56. if(vis[y]!=k&&cut[y]) ++num,vis[y]=k;
  57. if(!vis[y]) dfs(y);
  58. }
  59. }
  60. int main()
  61. {
  62. freopen("input.in","r",stdin);
  63. freopen("output.out","w",stdout);
  64. for (int ca=;;++ca)
  65. {
  66. int n=,m;
  67. read(m);
  68. if(!m) exit();
  69. memset(dfn,,sizeof(dfn));
  70. memset(vis,,sizeof(vis));
  71. memset(cut,,sizeof(cut));
  72. memset(lin,,sizeof(lin));
  73. hl=k=num=len=;
  74. ans=;
  75. for (int i=;i<=m;++i)
  76. {
  77. int x,y;read(x);read(y);
  78. n=max(n,max(x,y));
  79. add(x,y);add(y,x);
  80. }
  81. for (int i=;i<=n;++i)
  82. if(!dfn[i]) root=i,tarjan(i,i);
  83. for (int i=;i<=n;++i)
  84. if(!vis[i]&&!cut[i])
  85. {
  86. ++k,cnt=num=;
  87. dfs(i);
  88. if(!num) hl+=,ans*=cnt*(cnt-)/;
  89. if(num==) hl++,ans*=cnt;
  90. }
  91. printf("Case %d: %lld %lld\n",ca,hl,ans);
  92. }
  93. return ;
  94. }

D8 双连通分量的更多相关文章

  1. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Acce ...

  2. 【Codefoces487E/UOJ#30】Tourists Tarjan 点双连通分量 + 树链剖分

    E. Tourists time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard inpu ...

  3. 【BZOJ-2730】矿场搭建 Tarjan 双连通分量

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Statu ...

  4. hihoCoder 1184 连通性二·边的双连通分量

    #1184 : 连通性二·边的双连通分量 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老 ...

  5. HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...

  6. 点/边 双连通分量---Tarjan算法

    运用Tarjan算法,求解图的点/边双连通分量. 1.点双连通分量[块] 割点可以存在多个块中,每个块包含当前节点u,分量以边的形式输出比较有意义. typedef struct{ //栈结点结构 保 ...

  7. Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】

    一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...

  8. poj3177 && poj3352 边双连通分量缩点

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12676   Accepted: 5368 ...

  9. 【POJ 2942】Knights of the Round Table(点双连通分量,二分图染色)

    圆桌会议必须满足:奇数个人参与,相邻的不能是敌人(敌人关系是无向边). 求无论如何都不能参加会议的骑士个数.只需求哪些骑士是可以参加的. 我们求原图的补图:只要不是敌人的两个人就连边. 在补图的一个奇 ...

随机推荐

  1. Ext-JS-Modern-Demo 面向移动端示例

    基于Ext Js 6.5.2 面向移动端示例,低于此版本可能存在兼容问题,慎用 已忽略编译目录,请自行编译运行 Sencha Cmd 版本:v6.5.2.15 git地址:https://github ...

  2. [原][openstack-pike][controller node][issue-2][glance] Could not parse rfc1738 URL from string 'mysql+pymysql=http://glance:glance@controller/glance'

    问题点 在手动上传镜像的时候:出现错误 Could not parse rfc1738 URL from string 'mysql+pymysql=http://glance:glance@cont ...

  3. CF 634A Island Puzzle

    A. Island Puzzle time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  4. Go etcd初探

    1.etcd集群的配置 SET IP1_2380=http://127.0.0.1:2380 SET IP1_2379=http://127.0.0.1:2379 SET IP2_2380=http: ...

  5. webpack使用小记

    前言 webpack是目前前端开发必不可少的一款模块加载器兼构建工具,它能极其方便的处理各种资源的打包和使用, 让前端开发获得与后端开发几乎一致的体验. webpack特点 webpack 是以 co ...

  6. springmvc中为我们做了什么

    这应该是每个使用框架的人应该自问的.这就要从没有使用框架时说.在没用框架开发web应用时,自己是怎么开发的,就是写servlet,jsp. 使用springmvc后,使用Controller注解,其实 ...

  7. 10.17小结:table.copy() 和 distinct 查询

    1. 当datatable 已存在于一个dataset中时,可以使用 ds.tables.add(dt.copy()) 来向dataset 中添加datatable; 2. 当datarow已存在于一 ...

  8. 无网络 使用pip安装mxnet

    # 在有网络的同系统机器上运行以下命令:pip download mxnet# 目前mxnet版本为1.3.0,执行后当前目录得到以下文件: # . # ├── certifi--py2.py3-no ...

  9. Python学习之旅(九)

    Python基础知识(8):集合 集合:由不同元素组成,无序的,不重复的序列 补充知识:可变类型:列表.字典:不可变类型:数字.字符串.元组 使用大括号{}或set()方法定义集合 se=set(&q ...

  10. iota

    这算法由SGI专属,并不在STL标准之列.它用来设定某个区间的内容,使其内的每一个元素从指定的value值开始,呈现递增状态.它改变了区间内容,所以是一种质变算法. template <clas ...