图的连通
来源:互联网 发布:淘宝店铺视频制作 编辑:程序博客网 时间:2024/05/22 16:04
关于判断图是否连通,一般需要先了解:
1. DFS和BFS这两个搜索算法,或者说是遍历方式(实际上树的前中后序遍历和层次遍历分别就是DFS和BFS的运用)。
2. 对于图的建立此处就不在介绍了
(这里不对UnionFind在连通性的判断上做介绍。)
连通图的概念
这个链接里面,都有讲到,这个。
可能大神讲到有点抽象,小弟就做了如下图解(如有误,喷我)。
此外,链接中所讲的双连通分量,可以理解为连通度大于等于2的情况,也就是
其中的dfs[],和low[]这两个数组可以,结合这个动图理解,这个动图。
万能模板——Tarjan
之所以我认为这个Tarjan是一个解决连通性问题的利器(厉害还是Tarjan厉害)。
/* *邻接表存储 *无向图求割点*/vector<int> G[MAXN];int dfn[MAXN], low[MAXN], keyNode[MAXN];bool vis[MAXN];void Tarjan(int u, int start, int &cnt, int &res, int &rd) { cnt++; dfn[u] = low[u] = cnt; for(int i = 0; i < (int)G[u].size(); ++i) { int v= G[u][i]; if(!vis[v]) { Tarjan(v, start, cnt, res, rd); if(low[v] >= dfn[u]) { if(u != start && !vis[u]) keyNode[res] = u, vis[u] = true, res++; else if(u == start) rd++; } if(low[v] < low[u]) low[u] = low[v]; } else if(dfn[v] < low[u]) { low[u] = dfn[v]; } }}int keyVertex(int n) { int cnt = 0, res = 0; for(int i = 0; i <= n; ++i) dfn[i] = 0, vis[i] = false; for(int i = 0; i < n; ++i) { if(!dfn[i]) { int rd = 0; Tarjan(i, i, cnt, res, rd); if(rd > 1 && !vis[i]) keyNode[res] = i, vis[i] = true, res++; } } return res;}
/* *邻接表存储 *无向图求割边*/struct KeySide{ int from, to;}keySide[MAXE];vector<int> G[MAXN];int dfn[MAXN], low[MAXN];void Tarjan(int u, int &cnt, int &res) { ++cnt; dfn[u] = low[u] = cnt; for(int i = 0; i < (int)G[u].size(); ++i) { int v = G[u][i]; if(!dfn[v]) { Tarjan(v, cnt, res); if(low[v] > dfn[u]) keySide[res].from = u, keySide[res].to = v, res++; if(low[v] < low[u]) low[u] = low[v]; } else if(dfn[v] < dfn[u] - 1 && dfn[v] < low[u]) { low[u] = dfn[v]; } } } int keyEdge(int n) { int cnt = 0, res = 0; for(int i = 0; i <= n; ++i) dfn[i] = 0; for(int i = 0; i < n; ++i) if(!dfn[i]) Tarjan(i, cnt, res); return res;}
/* *无向图求连通分支*/vector<int> G[MAXN];int dfn[MAXN], low[MAXN];stack<int> S;void Tarjan(int u, int &cnt, int &res){ low[u] = dfn[u] = ++cnt; S.push(u); for(int i = 0; i < (int)G[u].size(); ++i) { int v = G[u][i]; if(!dfn[v]) { Tarjan(v, cnt, res); if(low[u] > low[v]) low[u] = low[v]; } else if(low[u] > dfn[v]){ low[u] = dfn[v]; } } if(low[u] == dfn[u]) { int v; res++; do{ v = S.top(), S.pop(); cout<<v<<' '; }while(u != v); cout<<endl; }}void block(int n) { int cnt = 0, res = 0; for(int i = 0; i <= n; ++i) dfn[i] = 0; for(int i = 0; i < n; ++i) { if(!dfn[i]) { Tarjan(i, cnt, res); } }}
/* *有向图求连通分支*/vector<int> G[MAXN];int low[MAXN], dfn[MAXN], id[MAXN];bool inSta[MAXN];stack<int> S;void Tarjan(int u, int &cnt, int &res) { low[u] = dfn[u] = ++cnt; S.push(u), inSta[u] = true; for(int i = 0; i < (int)G[u].size(); ++i) { int v = G[u][i]; if(!dfn[v]) { Tarjan(v, cnt, res); if(low[u] > low[v]) low[u] = low[v]; } else if(inSta[v]) { if(low[u] > dfn[v]) low[u] = dfn[v]; } } //缩点 if(low[u] == dfn[u]) { int v; res++; do{ v = S.top(), S.pop(); inSta[v] = false; id[v] = res; }while(u != v); }}int slove(int n) { int cnt = 0, res = 0; for(int i = 0; i <= n; ++i) low[i] = dfn[i] = id[i] = 0, inSta[i] = false; for(int i = 1; i <= n; ++i) if(!dfn[i]) Tarjan(i, cnt, res); return res;}
就写到这吧,发现自己已经对于有向和无向的求解已经傻傻分不清了,过段时间做几道题,在看看应该能想明白。
0 0
- 连通图的强连通分支
- 图的连通
- 奇怪的连通图
- 图的连通
- 强连通图的算法
- 求图的连通分量
- 强连通图的算法
- 强连通图的算法
- 强连通图的算法
- 图的强连通分量
- 奇怪的连通图_1545
- 判断图的连通分量
- 图的--最小-连通-网
- hdu2767(图的强连通)
- 图的连通概念辨析
- [NOIp复习计划]:图的连通
- 图的点连通度边连通度总结
- 图的点连通度和边连通度
- Github搜索技巧-如何使用github找到自己感兴趣的项目
- js学习资料笔记合集,持续学习更新中,欢迎大牛们指点
- ABAP 生成ZIP压缩文件的代码
- android system 签名
- 动态规划总结
- 图的连通
- event
- 网络流量监控
- soc时钟系统4月17 一个周末玩了三四天啊 速八真不错
- CAP理论中的P理解
- 使用maven编译部署代码时,跳过Junit测试的办法
- Web.xml配置详解之context-param
- HDU 1495 非常可乐
- Android调用后台服务c# Webservice(源码)