UVA315---Network(连通性问题:求割点)
来源:互联网 发布:手机淘宝怎么注销不了 编辑:程序博客网 时间:2024/05/22 06:42
题目来源:https://vjudge.net/problem/UVA-315
题意
存在n个电话公司的网络连接站点,每个站点之间相互连通,是一个连通图,问,如果去掉一个站点,能够将整个网络体系变得不再连通,那么这样的店有几个?
思路
在这里利用深搜去实现寻找割点,下面讲一下几种情况,一一对应代码说一下。
图一:
这里的图一共有三个割点,编号分别是2 ,3,4,而去掉1或5,整个网络体系依旧是一个连通图。
图二:
此时在图一上加了一条红线,也即是将2,4连通,那么此时3便不是割点了,因为去掉3之后,可以通过2->4将整个图连通。
如果用深搜的思想去写,那么需要一个起点,也可以称为根节点,最终,整个图都会被遍历一遍,假设在这里,设点1为根节点(谁都可以)(无向图),那么整个遍历顺序就是:1->2->3->4->5,这样标记了编号之后,深搜经过的边就会构成名叫:深搜优先生成树的树形结构(树形结构不会有环)。也即是每个点都有一个访问时刻(num数组),那么分析一下存在割点的情况:
第一种:假设当前点围割点,那么访问时刻比它大的点与访问时刻比他小的点之间没有联系。
对于这一种情况,图一中的点3符合,而图二的点3不符合,明显看到2-4有条线跳过了3,那么我们该怎么判断当前点有没有被跳过呢?(点的编号越小,越靠近根哦)
主要还是那条红线,这条线并没有出现在深搜优先生成树中,所以叫做:反祖边(回退边),也就是能够从先序编号较大的点直接回到编号较小的点,所以根据这条红线,弄了一个数组low,low[4]=min(low[4],num[2]),所以由这个数组记录可以知道,4最高是可以回到点2的,所以去掉点3无所谓,所以在整个代码中,先序编号(num数组)记录了是整个深度优先生成树,他是连通的,而low数组记录的是当前点可以返回到编号最小的那个点的先序编号,比较的时候呢,我们可以比较low数组,比如:low[3]>low[4],可知,点4可以比3更接近根,所以可以跳过3,也就是说,去掉3,4依旧可以与比3更高的点相连接,使网络连通。
但是呢,难道我们真要一个一个比较吗?
图三:
那么,就像图三一样,如果真要一个个比较的话,也要比较low[3]与low[5]的关系,如果3的子节点有很多,那完了,铁定超时,所以我们可以直接把点3的所有子节点的low最小值赋给low[3],那样,当深搜回溯的时候,遇到3,如果此时low[3]是1(low[5]给的),那么和他自身的先序编号num[3]进行比较,说明他的子节点low的值有比它小的,也就是他的子节点与3上面的点有条边叫做反祖边(回退边),那说明3肯定不是割点。至于怎么赋值,可以在回溯的时候赋值呀。
但是呢,除此之外,还要特判这个点不是根节点,因为没有编号比根节点更小的了。。。你说是吧。。。
所以根节点还需要特判,怎么特判呢?
既然是树形结构,那么不存在环,所以当根节点的儿子数量大于1的时候,就说明他是割点了,如图:
对了,在图三里,5可不是1的儿子哦,因为那条绿色的线可没有参与组成深度优先生成树,他叫反祖边(回退边)。
至于代码里parent数组是做什么的,可以自行思考哦。
参考文章:http://www.cnblogs.com/llhthinker/p/4954082.html
代码
#include<cstdio>#include<vector>#include<cstring>#include<algorithm>using namespace std;vector<int> graph[110];//vector型邻接表存图int low[110],parent[110],num[110];bool vis[110];//标记是否访问过(形成树的过程)bool check[110];//当前这个点是否已经计算过(割点int number,ans;//number是编号void find_tree(int x){ low[x]=num[x]=number++;//赋初值,low和num一样 vis[x]=true;//标记已经访问过 int tmp=0;//为了验证根节点有几个儿子 0.0 for(int i=0; i<graph[x].size(); i++) { if(!vis[graph[x][i]]) { parent[graph[x][i]]=x; tmp++; find_tree(graph[x][i]); if(low[graph[x][i]]>=num[x]&&x!=1&&!check[x]) { ans++;check[x]=true; } else if(tmp>1&&x==1&&!check[x]) { ans++; check[x]=true; } low[x]=min(low[x],low[graph[x][i]]);//把x的low更新成包括他本身和他所有子节点的最小low值 } else if(parent[x]!=graph[x][i])//反祖边 { low[x]=min(low[x], num[graph[x][i]]);//把它赋成他的编号 } }}int main(){ int n; while(~scanf("%d",&n)&&n) { memset(low,0,sizeof(low)); memset(parent,0,sizeof(parent)); memset(num,0,sizeof(num)); int st,ed; for(int i=1;i<=n;i++) { graph[i].clear(); } while(~scanf("%d",&st)&&st) { while(getchar()!='\n') { scanf("%d",&ed); graph[st].push_back(ed); graph[ed].push_back(st); } } memset(vis,0,sizeof(vis)); memset(check,0,sizeof(check)); number=0; ans=0; find_tree(1); printf("%d\n",ans); }}
- UVA315---Network(连通性问题:求割点)
- UVA315 Network(tarjan求割点)
- uva315/poj1144 network 求割点
- uva315 Network 【tarjan-求割点】
- UVA315-Network(求割点个数,模板题)||tarjan
- UVa315 - Network
- UVA315-Network
- UVA315 Network
- uva315(求割点模板题)
- UVA315- Network(无向图割点)
- 连通性问题(算法)
- 连通性问题(connectivity)
- uva315 Network 【图论-tarjan-求桥】
- uva315
- uva315
- UVA315 && UVA 796 (求割点和桥,模版)
- 动态连通性问题(1)
- 动态连通性问题(2)
- 架构师入门笔记二 初识java容器
- 数据结构排序2
- DOS命令大全(经典收藏)
- 第十一题 数值的整数次方
- Python——Python文件中常见的if __name__ == '__main__': 的解析
- UVA315---Network(连通性问题:求割点)
- 请求路由标签
- Android 屏幕适配方案 引入百分比
- c语言文件操作:FOR 1.4题(知识储备)
- 使用python向C语言的链接库传递数组、结构体、指针类型的数据
- HDU 6070 二分查找 + 线段树 + 枚举
- 微信小程序尺寸单位rpx以及样式相关介绍
- 快速排序、二分法查找的PHP实现代码
- rsync配置备份服务器数据