求一个连通图的割点(去掉一个点后图不再连通)

题目:求一个连通图的割点,割点的定义是,如果除去此节点和与其相关的边,图不再连通,描述算法。

分析:

1. 最简单也是最直接的算法是,删除一个点然后判断连通性,如果删除此点,图不再连通,则此点是割点,反之不是割点(图的连通性一般通过深搜来判定,是否能一次搜索完 全部顶点);

2. 通过深搜优先生成树来判定。从任一点出发深度优先遍历得到优先生成树,对于树中任一顶点V而言,其孩子节点为邻接点。由深度优先生成树可得出两类割点的特性:

     (1)若生成树的根有两棵或两棵以上的子树,则此根顶点必为割点。因为图中不存在连接不同子树顶点的边,若删除此节点,则树便成为森林;

     (2)若生成树中某个非叶子顶点V,其某棵子树的根和子树中的其他节点均没有指向V的祖先的回边,则V为割点。因为删去v,则其子树和图的其它部分被分割开来。

仍然利用深搜算法,只不过在这里定义visited[v]表示为深度优先搜索遍历图时访问顶点v的次序号,定义low[v]=Min{visited[v],low[w],visited[k]},其中w是顶点v在深度优先生成树上的孩子节点;k是顶点v在深度优先生成树上由回边联结的祖先节点。

   割点判定条件:如果对于某个顶点v,存在孩子节点w且low[w]>=visited[v],则该顶点v必为关节点。因为当w是v的孩子节点时,low[w]>=visited[v],表明w及其子孙均无指向v的祖先的回边,那么当删除顶点v后,v的孩子节点将于其他节点被分割开来,从来形成新的连通分量。

#include <iostream>  
#include <string>  
#include <queue>  
using namespace std;  #define MAXN 100  struct ArcNode  
{  int adjVertex;       //边到的顶点  ArcNode *next;  
};  struct VNode  
{  string data;  ArcNode *firstArc;  
};  typedef VNode AdjList[MAXN];  struct Graph  
{  int vertexNum;  int arcNum;  AdjList vertexs;  
};  int Locate(Graph g,string str)  
{  for(int i = 0;i<g.vertexNum;i++)  {  if(str == g.vertexs[i].data)  return i;  }  return -1;  
}  void Create(Graph &g)  
{  string start,end;  cout << "请输入顶点和边数:"<<endl;  cin>>g.vertexNum>>g.arcNum;  for(int i = 0;i<g.vertexNum;i++)  {  cout<<"请输入第"<<i<<"个顶点:"<<endl;  cin>>g.vertexs[i].data;  g.vertexs[i].firstArc = NULL;  }  for(int i = 0;i <g.arcNum;i++)  {  cout<<"请输入第"<<i<<"条边的起始和结束顶点"<<endl;  cin>>start>>end;  int m = Locate(g,start);  int n = Locate(g,end);  ArcNode *node = new ArcNode;  node->adjVertex = n;  node->next = g.vertexs[m].firstArc;  g.vertexs[m].firstArc = node;  ArcNode *node1 = new ArcNode;  node1->adjVertex = m;  node1->next = g.vertexs[n].firstArc;  g.vertexs[n].firstArc = node1;  }  
}  void Print(Graph g)  
{  for(int i = 0;i<g.vertexNum;i++)  {  cout << g.vertexs[i].data;  ArcNode *p = g.vertexs[i].firstArc;  while(p)  {  cout<<"-->"<<g.vertexs[p->adjVertex].data;  p = p->next;  }  cout <<endl;  }  
}  int FirstAdjVex(Graph g,int v)//返回v的第一个邻接顶点序号  
{  ArcNode *p = g.vertexs[v].firstArc;  if(p!= NULL)  return p->adjVertex;  else  return -1;  
}  int NextAdjVex(Graph g,int v,int w) //返回顶点v相对于w的下一个邻接点的序号  
{  ArcNode *p = g.vertexs[v].firstArc;  while(p)  {  if(p->adjVertex == w)  break;  p = p->next;  }  if(p->adjVertex !=w || !p->next)  return -1;  return p->next->adjVertex;  
}  //求割点  
int countN;  
int visted[MAXN];  
int low[MAXN];  void DFSCutPoint(Graph g,int v0)  
{  int min = 0,w;  visted[v0] = min = ++countN;;//v0是第count个访问的顶点,min的初值为visited[v0],即v0的访问次序   for(ArcNode *p = g.vertexs[v0].firstArc;p;p=p->next)  {  w = p->adjVertex;  if(!visted[w])  {  DFSCutPoint(g,w);//从第w个顶点出发深搜,查找并输出关节点(割点),返回前求得low[w]    if(low[w] < min)//如果v0的孩子节点w的low[]小,说明孩子节点还与其他节点(祖先)相邻    min = low[w];  if(low[w]>=visted[v0] ) //v0的孩子节点w只与v0相连,则v0是关节点(割点)    cout<<g.vertexs[w].data<<" ";  }  else if(visted[w] < min)//w已访问,则w是v0生成树上祖先,它的访问顺序必小于min    min =visted[w];  }  low[v0] = min;//low[v0]取三者最小值  
}  void FindCutPoint(Graph g)  
{  visted[0] = true;  for(int i = 1;i<g.vertexNum;i++)  visted[i] = false;  ArcNode *p=g.vertexs[0].firstArc;  int v = p->adjVertex;  DFSCutPoint(g,v);  if(countN < g.vertexNum)  {  cout << g.vertexs[0].data<<" ";  while(p->next)  {  p = p->next;  v = p->adjVertex;  if(!visted[v])  DFSCutPoint(g,v);  }  }  
}  int main()  
{  Graph g;  Create(g);  cout<<"割点如下: "<<endl;    FindCutPoint(g);  return 0;  



转载于:https://www.cnblogs.com/tham/p/6827246.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入浅出 Java Concurrency (6): 锁机制 part 1[转]

前面的章节主要谈谈原子操作&#xff0c;至于与原子操作一些相关的问题或者说陷阱就放到最后的总结篇来整体说明。从这一章开始花少量的篇幅谈谈锁机制。 上一个章节中谈到了锁机制&#xff0c;并且针对于原子操作谈了一些相关的概念和设计思想。接下来的文章中&#xff0c;尽可…

行为树

行为树(Behavior Tree)&#xff0c;有4大类型的Node&#xff1a; (1) Composites Node 组合节点&#xff0c;包括经典的&#xff1a;Sequence&#xff0c;Selector&#xff0c;Parallel * Selector Node 当执行本类型Node时&#xff0c;它将从begin到end迭代执行自己的Ch…

SCRUM 12.03

第二轮迭代从今天起正式开始了。12月3日&#xff0c;我们举行了一次组会。 第一轮迭代结束时&#xff0c;我们意识到第二轮迭代需要实现的功能主要如下&#xff1a; 在下次迭代的时候实现对多个网站的信息进行比较取最优惠的选择&#xff0c;目前我们劲针对了一个网站的信息进行…

阻止页面双击选中文本

轮播图实现中&#xff0c;发现当点击切换按钮时&#xff0c;如果用户点快乐&#xff0c;双击了按钮&#xff0c;就会选中文本。十分影响浏览效果&#xff0c;所以有了这篇文章。 IE以及谷歌下的解决办法&#xff1a; <div id"zell-carousel" class"zell-caro…

STL内嵌数据类型: value_type

使用stl库的时候一直对value_type这个东西理解的不是很好&#xff0c;可以说就是不理解。今天看了《STL源码剖析》才恍然大悟。这里稍作记录。 每个STL中的类都有value_type这种东西&#xff0c;通俗的说value_type 就是stl容器盛装的数据的数据类型&#xff0c;例如&#xff…

Boost.Python实现Python C/C++混合编程

导出函数 #include<string> #include<boost/python.hpp>using namespace std; using namespace boost::python;char const * greet() {return "hello,world";}BOOST_PYTHON_MODULE(hello_ext) {def("greet", greet); } import hello_ext pri…

swift UIActivityIndicatorView

// // ActivityIndicatorViewController.swift // UIControlDemo // // Created by on 14/12/1. // Copyright (c) 2014年 马大哈. All rights reserved. // import UIKit class ActivityIndicatorViewController: BaseViewController { var waitActivity:UIActivityIndi…

UE4打包后如何调试

在项目打包后发现有一个数组越界问题&#xff0c;然而无论是 Play in Editor或是 VS选为DebugGame后启动&#xff0c;游戏都没有任何问题&#xff0c;越界问题只在打包后出现。这里记录一下自己的Debug方法。 首先将项目以DebugGame配置打包&#xff1a; 更改打包配置&#xff…

asp.net 使用my97 datepicker实现前后两个日期的范围界定

说明&#xff1a;日期选择后&#xff0c;前面的日期小于等后面的日期&#xff0c;后面的日期大于等于前面的日期。点点看就知道了:) &#xff5e; 这里将周末日期不可选。代码如下&#xff1a; 1 <html xmlns"http://www.w3.org/1999/xhtml">2 <head runat…

james-2.3.2中的配置

james&#xff1a;1、解压缩2、先运行一遍3、修改配置 apps\james\SAR-INF\config.xml(1)postmaster(2)servername localhost --> abclocalhost j08.com --> abcj08.com 自动检查名称和IP设为false(3)注释掉RemoteAddrNotInNetwork(4)添加虚拟域名&#xff0c;指向localh…

Win7下安装配置gVim

本文根据vim官网的《Simple Steps to Help You Install gVim on Windows 7》【1】一文整理而成。 1. 下载gVim 在http://www.vim.org/download.php/pc 下找到“PC: MS-DOS and MS-Windows”&#xff0c;下载“gvim74.exe”【2】。 2. 安装gVim 1. 安装时可以选择更改目录&#…

ActiveReports 报表控件官方中文入门教程 (2)-创建、数据源、浏览以及发布

ActiveReports 报表控件官方中文入门教程 (2)-创建、数据源、浏览以及发布 原文:ActiveReports 报表控件官方中文入门教程 (2)-创建、数据源、浏览以及发布本篇文章将阐述首次使用 ActiveReports 报表控件 的方法&#xff0c;包括添加报表文件、绑定数据源以及如何发布报表等内…

C++ Lambda表达式基本用法

创建一个匿名函数并执行。采用的是配对的方括号[]。实例如下&#xff1a; 1 2 3 4 5 6 7 8 9 #include <iostream> using namespace std; int main() { []{ cout << "Hello,Worldn"; }(); } 我们也可以方便的将这个创建的匿名函数赋…

每日一测4(装箱与拆箱)

1、定义 装箱&#xff1a;用于在垃圾回收堆中存储值类型。装箱是值类型到 object 类型或到此值类型所实现的任何接口类型的隐式转换。 拆箱&#xff1a;从 object 类型到值类型或从接口类型到实现该接口的值类型的显式转换。 2、为什么要装箱&#xff1a; &#xff08;1&#x…

flex 正则表达式匹配规则

正则表达式扫描的优先级 1. 先根据空格&#xff0c;tab&#xff0c;回车分割字符串&#xff0c;作为正则表达式匹配的基础 2. 找到完全匹配的正则表达式&#xff0c;以排列在前面的优先级为高 3. 如果找不到匹配的表达式&#xff0c;那么从头开始截取字符串来查找合…

笔记本多硬盘win7下U盘安装Cnetos7引导问题!

CentOS7出来的时间已经不算短了&#xff0c;前段时间一直在虚拟机上使用&#xff0c;最近闲下来了&#xff0c;就像在自己的笔记本上装一个win7和Centos7的双系统体验以下实体机的效果&#xff0c;几经波折之后终于顺利的装上了WIN7和CentOS7的双系统&#xff01;在这里主要是想…

QString转char*的问题

QString tmp"abc"; char *p tmp.toLatin1().data()); QString tmp"abc"; char *p new char[1strlen(tmp.toLatin1().data())]; strcpy(p, tmp.toLatin1().data()); 运行模式两种方法都可以&#xff0c;调试模式&#xff0c;第一种方式无法得到QString的…

hdu 1870

水题。。。。 AC代码&#xff1a; #include <iostream> #include <queue> using namespace std; int main() {char str[1010];int i,k;while(scanf("%s",&str)!EOF){queue<char>q;for(i0;str[i]!B;i){if(str[i]()q.push(str[i]);if(str[i]))q.…

Linux Apache php MySQL 安装配置(Centos 6.4 yum安装)

一、yum准备 1.Yum&#xff08;全称为 Yellow dog Updater, Modified&#xff09;是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。 基于RPM包管理&#xff0c;能够从指定的服务器自动下载RPM包并且安装&#xff0c;可以自动处理依赖性关系&#xff0c;并且一次安…