无向图 割点

来源:互联网 发布:马鞍山网络大学专升本 编辑:程序博客网 时间:2024/04/30 11:34

1.定义:

割点:某个点是割点当且仅当删除该点和与该点相关联的边后图变得不连通。

桥(割边):某条边是割边当且仅当删除该边后图变的不连通。

双连通分支:图G的所有子图G'中,如果G'是连通的,则称G'是双连通子图。如果G'不是任何一个连通子图的真子图,那么图G'是双连通分支。特别的,点双连通分支又叫做块。

2.求割点,桥

对原图进行深度优先搜索,会生成一颗深度优先搜索生成树。定义dfs[u]为u在深度优先搜索生成树中被遍历到的序号,low[u]为u或者他的子树中可以通过非父子边追溯到的最早结点。

那么一个顶点是割点,满足下列条件之一:

1).u是树根,u有两个或两个以上的分支;

2).u不是树根,(u,v)是树边且low[v]>=dfn[u]。

边(u,v)是桥,当且仅当low[v]>dfn[u],(u,v)是树边。

下面是自己总结了多人的模板后写的,自已的模板(我的风格的)

性质:low[]的值相等的点为同一个连通分量。

int root, cnt,son;

//  root记录根下标,son为根直接连接的儿子的数量,当其>1时根为割点。
int vis[Max], dfn[Max], low[Max];  

//  dfn[i]为第i个结点在搜索树中的深度,low[u]定义为u或者u的子树中能够通过非父子边追溯到的最早的节点的DFS开始时间 如下图:红色为low的值,蓝色为dfn的值

无向图 <wbr>割点模板

证明1:

  

       假设DFS遍历的第一个节点v不是割点,那么则有low[v]=dfn[v]=1,继续对v的孩子节点u遍历,必然有low[u]>=dfn[v],按照第二条性质,则v是割点,但我们已经假设v不是割点。这是由于v是DFS遍历的起始节点,在遍历序列中v没有祖先节点,v的所有后继节点能追溯到最早的祖先节点最多也就是v了,不可能比v再早了,因此必须把DFS遍历的第一个节点v单独考虑,那么怎么判断v是不是割点呢?

      例如上图,设v是DFS序列访问的第一个节点,对v的孩子节点u和u的所有孩子节点进行DFS遍历并标记为已经访问后,如果v的另一个孩子节点k没有被标记为已经访问,那么u和k之间一定不存在边,也就是说u和k之间的连通必然需要点v,因此如果v是DFS遍历的第一个节点,对v是否为割点的判断方法是:看v是不是有多个孩子,如果有则v是割点。

证明2:

      如果v不是DFS遍历的第一个节点,那么对于v的所有后继节点来说,如果v不是割点(也就是如果删掉点v,剩下的图还是连通图),那么v的后继节点必然能追溯到DFS遍历序列中v的祖先节点,也就是v的后继节点中存在到达DFS序列中v的祖先的路径,因此当DFS回溯到v节点时对于v的所有后继节点u来说,都有low[u]<dfn[v]。

      如果v是一个割点,对所有v的后继节点u进行DFS后,必然有low[u]>=dfn[v],这是因为,当遍历v并将其锁定后,到达v的祖先节点的路径已经被封死,v的后继节点必然不可能访问到v的祖先节点,因此,必然有low[u]>=dfn[v]。

#include "iostream"#include "vector"#include "fstream"using namespace std;std::vector<vector<int> > edge;std::vector<int> low;std::vector<int> depth;std::vector<bool> cut;std::vector<bool> visited;int vertexnum;int edgenum;void initialvector(){edge.resize(vertexnum);//路径数组low.resize(vertexnum,10000);//low[u]为u或者他的子树中可以通过非父子边追溯到的最早结点,low[]的值相等的点为同一个连通分量depth.resize(vertexnum);//结点在搜索树中的深度,有很多是使用时间编号cut.resize(vertexnum,false);//割点数组visited.resize(vertexnum,false);//记录遍历节点}void getData(){//获取数据ifstream in("data");in>>vertexnum>>edgenum;initialvector();int from,to;while(in>>from>>to){//无向图edge[from].push_back(to);edge[to].push_back(from);}}void dfs(int current,int parent,int dep){visited[current] = true;depth[current] = dep;low[current] = dep;int child = 0;for (std::vector<int>::iterator i = edge[current].begin(); i != edge[current].end(); ++i){if(*i != parent && visited[*i]){low[current] = min(low[current],depth[*i]);//不知道改为low[current] = min(low[current],low[*i]);可不可以}if(!visited[*i]){//遍历未访问节点dfs(*i,current,dep+1);child++;//记录孩子数low[current] = min(low[current],low[*i]);//更新current节点,此时current子节点的low值已经确定if((current == 0 && child > 1)||(current != 0 && low[*i] >= depth[current])){cut[current] = true;}//如果根结点有大于1个的儿子,那么根结点是割点||如果对于点u的某个儿子v,有low[v] >= dep[u],那么u就是一个割点}}}int main(int argc, char const *argv[]){getData();  dfs(0,0,0);for (int i = 0;i < cut.size();i++){if(cut[i]){cout<<i<<" ";}}cout<<endl;return 0;}



data:13 17
0 1
0 2
0 5
0 11
1 2
1 3
1 6
1 7
1 12
3 4
6 7
6 8
6 10
7 10
9 11
9 12
9 12
其中0->A,1->B,......

参考:

http://blog.csdn.net/cxllyg/article/details/7610265

http://blog.sina.com.cn/s/blog_691ce2b701017gdx.html

http://blog.csdn.net/xinghongduo/article/details/6202646

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大便过粗把马桶堵了怎么办 大便硬的像石头拉不出来怎么办 家里埋在地下的水管漏水怎么办 埋在墙里的水管漏水怎么办 开发商暗埋水管热熔接头漏水怎么办 钻墙把水管钻破了怎么办 钻墙时不小心把水管钻破了怎么办 孩子把同桌的铅笔盒弄坏了怎么办 水管伐坏了物业不给修怎么办 卫生间埋在地下的水管漏水怎么办 埋在地下的水管冻住了怎么办 洗脸盆下水管有眉笔掉堵了怎么办 楼上打空调眼导致墙面潮湿怎么办 阳台做防水了又贴砖还漏水怎么办 洗菜盆里的盖子吸住拔不起来怎么办 掉小区阴井盖里物业不管怎么办 卫生间下水道被头发堵了怎么办妙招 久量时尚夜光台灯不亮了怎么办 我想做水电暖工程没有资质怎么办 修手机被弄丢了没有开维修单怎么办 手机去维修被老板弄丢了怎么办 5年保修期过后房子楼顶漏水怎么办 墙内水管漏水怎么办3步骤巧维修 下面有地暖下面水管漏水怎么办 热水器接的塑料水管子漏水怎么办 电热水器烧热水时热水管漏水怎么办 户户通位置锁定模块异常1怎么办 户户通位置锁定模块异常3怎么办 逆战安全系统检测客户端异常怎么办 电视户户通位置信息模块异常怎么办 苹果手机wi-fi模块坏了怎么办 xp本地连接受限制或无连接怎么办 公司没帮二级建造师延续注册怎么办 考造价师考过了年限不够怎么办? 上海众非称重不显示数字怎么办 宝骏630防火墙隔热棉掉了怎么办 冷车启动水温报警灯亮了怎么办 租铺位面积比合同面积小怎么办 农村村民建房领居不肯签名怎么办 车祸死者家属不来协商赔偿怎么办 26岁想回去当老师了怎么办