问题概述:给你一个无向联通图,你要在图中标记一些点,使得这个图中的任意一个点消失了,剩余的点都可以通

过一条路径到达你某个标记的点。问你最少需要选择多少个点,并且在最优的情况下有多少总选点方案,(每个样

例输入的第一个数m表示图中有多少条边,当m为0时读入结束)

输入样例:                                对应输出:

9                                                Case 1: 2 4

1 3   4 1

3 5   1 2

2 6   1 5

6 3   1 6   3 2

UVALive - 5135

点双连通图:该无向图中的任意两个顶点间都存在两条点不相交的路径

(或是说该图中去掉任意一个点都不会影响其联通性)

定理:

①如果一个连通图不是点双联通图,那么必定存在至少一个点,如果这个点消失,图就会被分成多块,这样的点也

被称为割点

②点双联通分量一定是边双联通分量(除两点一线的特殊情况),反之不一定

③点双联通分量可以有公共点

Trajan主要原理:

time[k]:第一次遍历到k点的时间

low[k]:k点所在点双联通分量子图中第一个被搜到的点的time值

vis[k]:k点是否已经遍历

主要思路:一般来讲无论求解点双联通还是边双连通都是边入栈,如果点入栈,而因为性质③,你将一个点出栈

后,还可能有别的点双联通分量包含它,所以点入栈会导致一些错误和麻烦,但这里有种方法可以不需要栈,大概

思路是把所有的割点找出来(割点的time[]值一定会小于等于他搜索子树儿子点的low[]值,至于为什么?很显然如果一个点不是割点,那么它必定在一环上或它自身是一个点双联通分量,考虑前者:那么这个点的深搜子树一定

与他的某个父亲相连接,这样这个点儿子的low[]值就会是这个点某个父亲的low[]值,所以一定小于本身的time[]

值;考虑后者,它就不存在深搜子树更没有儿子,根本不会比较),然后再搜索一遍找出所有在同一点双联通分量

中的点即可。

注意:搜索对于根节点因为它没有父亲节点,所以无法通过上述方法判断根是否是割点,那怎么办?如果根有两个

搜索子树,那么它一定是个割点,反之不是

搜索过程:

→当点k有与点c相连,如果此时(time[k]时)c没有搜过,搜索c点,当c点及其子树搜索完毕回溯后,low[k] =

min(low[k], low[c]),如果此时low[c]的值>=time[k]的值,则说明点k是割点,否则不是

→当点k有与点c相连,如果此时(time[k]时)c已经搜过,low[k] = min(low[k], time[c])

期间保证:每个点每条边都只被搜索1次,且必须搜索1次,复杂度n+m,

此题题解:

看懂这题后第一眼想到是此图有多少个点双联通分量,那么就至少需要标记多少个点,然后情况数就是所有点双联

通分量中点个数的乘积,但没这么简单,要注意以下两点:

①:如果这个图本身是个点双联通分量,那么还是必须要标记两个点,因为有可能标记的点会被去掉,情况数就是

n*(n-1)/2,其中n为图中点的数量

②:如果一个点双联通分量中有不止一个割点,那么这个点双联通分量中就不需要标记任何一个点,因为其中一个

割点被去掉,还可以走另外一个割点到另一个双连通分量中

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
vector<int> G[50005];
set<int> st;
int n, t, sum, cutsum, vis[50005], low[50005], time[50005], cut[50005];
void Tarjan(int u, int p);
void Sech(int u);
int main(void)
{int i, m, u, v, cas = 1;long long bet, ans;while(scanf("%d", &m), m!=0){cutsum = 0;t = n = 1;memset(vis, 0, sizeof(vis));memset(cut, 0, sizeof(cut));for(i=1;i<=m+2;i++)G[i].clear();for(i=1;i<=m;i++){scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);n = max(n, max(v, u));}Tarjan(1, 0);memset(vis, 0, sizeof(vis));st.clear();ans = 1, bet = 0;for(i=1;i<=n;i++){sum = 0;if(vis[i]==0 && cut[i]==0){st.clear();Sech(i);if(st.size()==1){ans *= sum;bet++;}}}if(cutsum==0)printf("Case %d: 2 %lld\n", cas++, (long long)n*(n-1)/2);elseprintf("Case %d: %lld %lld\n", cas++, bet, ans);}return 0;
}void Tarjan(int u, int p)
{int i, v, child = 0;vis[u] = 1;low[u] = time[u] = t++;for(i=0;i<G[u].size();i++){v = G[u][i];if(v==p)continue;if(vis[v]==0){child++;Tarjan(v, u);low[u] = min(low[v], low[u]);if(p==0 && child>1 || p!=0 && low[v]>=time[u])cut[u] = 1,  cutsum++;}elselow[u] = min(low[u], time[v]);}
}void Sech(int u)
{int i, v;sum++;vis[u] = 1;for(i=0;i<G[u].size();i++){v = G[u][i];if(cut[v])st.insert(v);         /*因为一个割点可能会被不同的点搜到,所以这里要用set防重*/if(cut[v] || vis[v])continue;Sech(v);}
}

Tarjan点的双联通(寻找割点)相关推荐

  1. 【9.22校内测试】【可持久化并查集(主席树实现)】【DP】【点双联通分量/割点】...

    1 build 1.1 Description 从前有一个王国,里面有n 座城市,一开始两两不连通.现在国王将进行m 次命令,命令可 能有两种,一种是在u 和v 之间修建道路,另一种是询问在第u 次命 ...

  2. Tarjan边的双联通

    1076 2条不相交的路径 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 给出一个无向图G的顶点V和边E.进行Q次查询,查询从G的某个顶点V[s] ...

  3. Tarjan算法 (强联通分量 割点 割边)

    变量解释: low 指当前节点在同一强连通分量(或环)能回溯到的dfn最小的节点 dfn 指当前节点是第几个被搜到的节点(时间戳) sta 栈 vis 是否在栈中 ans 指强连通分量的数量 top ...

  4. POJ 3352 Road Construction ; POJ 3177 Redundant Paths (双联通)

    这两题好像是一样的,就是3177要去掉重边. 但是为什么要去重边呢??????我认为如果有重边的话,应该也要考虑在内才是. 这两题我用了求割边,在去掉割边,用DFS缩点. 有大神说用Tarjan,不过 ...

  5. [BZOJ1123][POI2008]BLO(tarjan求点双+树形dp)

    题目描述 传送门 题目大意:给出一个n个点m条边的无向连通图,问去掉每一个点之后存在多少点对不连通. 题解 tarjan求点双联通分量,对于每一个点双建立一个虚拟的节点,然后将这个点双的所有节点都连接 ...

  6. 『Tarjan算法 无向图的双联通分量』

    无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...

  7. POJ 3694Network(Tarjan边双联通分量 + 缩点 + LCA并查集维护)

    [题意]: 有N个结点M条边的图,有Q次操作,每次操作在点x, y之间加一条边,加完E(x, y)后还有几个桥(割边),每次操作会累积,影响下一次操作. [思路]: 先用Tarjan求出一开始总的桥的 ...

  8. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E) 割点: 对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点 割边(桥) 若对于e∈E,从图中删去边e之 ...

  9. bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双

    Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...

最新文章

  1. Python3和Raspberry Pi最全面最直接的课程
  2. 跟我学交换机配置(三)
  3. VB高效导入Excel2003和Excel2007文件到MSHFlexGrid控件显示
  4. java排队买票_【排队买票】 (Java代码)
  5. Android 弱引用和软引用
  6. 2016年第七届蓝桥杯 - 国赛 - C/C++大学B组 - D. 机器人塔
  7. Oracle primary,unique,foreign 区别,Hibernate 关联映射
  8. C#中ref和out的使用小结
  9. Python3标准库built-in、itertools、functools中的生成器
  10. mongodb 持久化 mysql_最详细的python爬虫指南(四):持久化操作(mongoDB、mysql)...
  11. 利用数据缓存加速文件备份
  12. mysql交换分区_对MySQL交换分区的实践
  13. height100%不能生效问题解决
  14. 2017 ACM-ICPC Asia Shenyang (ICPC亚洲沈阳赛区)
  15. java web邮件收发组件
  16. 将自己开发的vue组件库发布到npm
  17. 你所想要了解的美国人工智能专业
  18. 【网站】作为技术人可能要用到的IT技术网址清单,欢迎评论补充
  19. html怎么给文字添加视频链接,视频加文字水印,视频加图片水印,视频加外部链接,一个软件全部搞定...
  20. 开源数据库迁移工具canal

热门文章

  1. 线上python课程一般多少钱-参加Python培训机构要花多少钱
  2. python是干什么用的-python是做什么用的 python有什么用 - 驱动管家
  3. 怎样学好python编程-Python编程怎么学习好?老男孩Python入门
  4. 自学python顺序-Python学习之调换顺序
  5. asp.net_php_jsp,对ASP、JSP、PHP、ASP.NET进行实际应用%统计
  6. Vue3.0 + Ts 项目框架搭建四:配置 Svg-Icon、Icon图标
  7. 常用编码软件简单使用记录 1 : 自主编码器
  8. 基于HEVC 的UHD(超高清 4K)视频的主观质量评价
  9. android调webview的方法,Android中的WebView详解
  10. 拖拽 开发 easyui php,Easyui-Builder