poj 1523 求无向图所有割点以及删除割点后连通分量个数 给出详细算法思路
来源:互联网 发布:2018pscc是什么软件 编辑:程序博客网 时间:2024/05/29 07:25
题意
- 无向图找出每个割点,然后求出删除这个割点所得的连通分量个数
- 节点编号在1-1000,但没说按顺序给出
思路
- 无向图求所有割点是一类经典问题,这篇blog就以这题为例简单介绍一下求解的算法思路
- 我们希望在O(n+m)的时间里求出所有的割点
- 首先,总体思路是对图进行dfs操作,dfs的过程其实对应了一棵dfs搜索树,而我们就利用这棵搜索树的独特性质,来解决求割点的问题
- dfs过程是,当我们搜索到节点u时,会遍历和u有边链接的所有节点v,这里有两种情况,一是v已经被搜索过了,二是v还没有被搜索过
- 对于第二种情况,我们自然会继续dfs(v)
- 而对于第一种情况,在无向图中,存在一个很好的性质。即v节点一定是dfs树中,u的一个祖先节点(或者u本身,这个情况可以通过把父亲节点id作为参数传给dfs避免掉,详细参见代码)。这个性质通过画个事例,然后反证法,很容易证明。这种情况中的边(u, v),我们称之为反向边
- 我们根据这个性质,可以得到一个引理1:若u是dfs树中的非根节点,则u是割点,当且仅当,dfs树中存在一个u的孩子节点v,以v为根的子树中,任意节点都没有连到u的祖先节点的反向边
- 而当u是根节点时,则u是割点的充要条件是,在dfs树中u的孩子节点数超过1
- 这个证明根据之前我们说的性质,和割点的定义不难推出
- 具体实现的时候,我们通过维护两个数组pre和low来实现
- pre记录一个时间戳,即pre[u]记录u是第几个被访问的节点
- low[u]记录以u为子树的节点中,反向边连到最早被访问的节点的pre值
- 具体到这个题里,要求删除节点u后的联通分量个数,只要统计一下满足引理1的节点v的个数即可知道
- 注意:节点编号不是连续排布以及图可能不连通的问题
实现
#include <iostream>#include <cstdio>#include <cmath>#include <map>#include <set>#include <cstring>using namespace std;const int maxn = 1e3+5;map<int, set<int> > g;map<int, int> pre;map<int, int> low;int count = 0;map<int, int> cutNum;int dfs(int u, int fa){ low[u] = pre[u] = ++count; int child = 0; for (set<int>::iterator it = g[u].begin(); it != g[u].end(); it++){ int v = *it; if (fa == v){ continue; } if (!pre[v]){ child++; low[u] = min(low[u], dfs(v, u)); if (low[v] >= pre[u]){ cutNum[u]++; } } else{ low[u] = min(low[u], pre[v]); } } if (fa == -1 && child == 1){ cutNum.erase(cutNum.lower_bound(u)); } else if (fa != -1 && cutNum.find(u) != cutNum.end()){ cutNum[u]++; } return low[u];}int main(){ for (int t=1;true;t++){ int u, v; g.clear(); pre.clear(); cutNum.clear(); low.clear(); count = 0; while (scanf("%d", &u) != EOF && u){ scanf("%d", &v); g[u].insert(v); g[v].insert(u); } if (!g.size()){ break; } for (map<int, set<int> >::iterator it = g.begin(); it != g.end(); it++){ int u = it->first; if (!pre[u]){ dfs(u, -1); } } printf("Network #%d\n", t); if (!cutNum.size()){ puts(" No SPF nodes"); } for (map<int, int>::iterator it = cutNum.begin(); it!=cutNum.end();it++){ int u = it->first; int num = it->second; printf(" SPF node %d leaves %d subnets\n", u, num); } puts(""); } return 0;}
阅读全文
0 0
- poj 1523 求无向图所有割点以及删除割点后连通分量个数 给出详细算法思路
- Tarjan算法求BCC(无向图连通块、割边、割点)
- 关于求无向图的连通分量的个数
- poj 1532 【求无向图的所有割点 以及 该点分成的BCC数目】
- 求无向连通图的最小割点详解以及java源代码实现
- 求无向连通图的割点
- 求无向连通图的割点
- 求无向连通图的割点(图论)
- 求无向连通图的割点
- 求无向图的连通分量 算法
- POJ 1144 Network Tarjan 求无向图的割点的个数 Tarjan 模板题
- 超详细Tarjan算法总结,求强连通分量,割点,割边,有重边的割边
- 无向图dfs求连通分量
- 求无向图的连通分量
- poj1523—SPF(tarjan算法求无向图中所有的割点)
- POJ 1523 SPF(割点所割连通分量数)
- POJ 1523 SPF(割点所割连通分量数)
- POJ 1523 SPF(割点所割连通分量数)
- 项目问题
- Linux下Shell编程错误记录
- zepto框架学习日记
- bzoj2056 gift? 高精度?
- 牛客网js编程的输入输出
- poj 1523 求无向图所有割点以及删除割点后连通分量个数 给出详细算法思路
- elasticsearch5.4.0 java开发记录三
- Hibernate框架常用配置文件
- Ubuntu 联网 eht0没有问题
- 再使用vue 2.0 的时候碰到的坑,日后继续跟进
- [agc006c]Rabbit Exercise
- bzoj2796 [Poi2012]Fibonacci Representation
- java反射机制的运用
- Java面试题全集