C++实现计算关节点数量

关节点算法

本篇文章将贴出,基于深度优先遍历计算关节点数量的代码,并附带一定的讲解,可供大家参考学习,本来想从CSDN抄一份代码的,结果这里代码太长了,效果看起来也不怎么样
特别鸣谢 :在我想算法时获得BUFF《了了的祝福》,居然真的有用
当然,代码主题部分与CSDN能找到的一个关节点数量求解问题的代码接近,确实借鉴了,但他对于最后根节点是否是关节点的判断有误,这里是修正版。

提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


一、什么是关节点?

在一个无向连通图G(V, E)中,可能存在某个(或多个)结点 a,使得一旦删除 a 及其相关联的边,图G将不再是连通图,则称结点 a 为图G的关节点。

二、

1.代码贴图

算了不简介了,大家应该都看过算法了,不然不会做这种题,我就划个水,我猜大家大部分是来找代码的

#include <iostream>
using namespace std;

struct ENode {
	int adjVex;
	ENode* nextArc;
};

ENode** a;//邻接表声明

int tm = 0;
int d[100], low[100];//两个辅助数组,d[u]记录结点u被访问的时间,
//low[u]是u的最低深度优先数,
int sum = 0;//记录关节点数量
int parent[100];//parent[u]记录u的父节点
int cotl = 0;//用来判断根节点是不是关节点


void DFS(int u, int p) {//深度优先遍历,过程中补上d,low,parent数组的值
	ENode* w;	
	low[u] = d[u] = tm++;
	for (w = a[u]; w; w = w->nextArc) {
		int v = w->adjVex;
		if (u == 0 && w != a[0] && d[v] == -1)cotl++;//判断根结点是不是关节点
		
		if (d[v] == -1) 
		{
			DFS(v, u);
			if (low[u] > low[v])
				low[u] = low[v];
		}
		else if (v != p && low[u] > d[v])
				low[u] = d[v];
			else if (v == p)
				parent[u] = v;
		
	}
}


void Sum(int n) {//通过遍历每一个结点i,每个结点和他的每一个孩子j比较,
//low[j] >= d[i]表示i是关节点,或者是根
//注意是从1开始,代表直接略过根没有判断,所以i必定是关节点
	int i, j;
	for (i = 1; i < n; i++) {
		for (j = 1; j < n; j++) {
			if (parent[j] == i) {
				if (low[j] >= d[i]) {
					sum++;
					break;
				}
			}

		}
	}
}

int main() {
	int i;
	int cot = 0;
	int n, e;
	int u, v;
	ENode* t;
	cin >> n >> e;
	a = new ENode * [n];
	for (i = 0; i < n; i++)//初始化
		a[i] = NULL;

	for (i = 0; i < e; i++) {//建立邻接表
		cin >> u >> v;
		t = new ENode;
		t->adjVex = v;
		t->nextArc = a[u];
		a[u] = t;

		t = new ENode;
		t->adjVex = u;
		t->nextArc = a[v];
		a[v] = t;
	}

	for (i = 0; i < n; i++)//初始化
	{
		d[i] = -1;
		parent[i] = -1;
	}
		
	DFS(0, -1);//第一个参数u是当前访问结点,第二个参数p是u的父节点
	Sum(n);//计算根节点数量
	if (cotl > 0)sum++;//对根结点进行判断,是否是关节点。
	cout << sum << endl;
	return 0;
}

2.特别解析

对于我对根结点的判断方法:

if (u == 0 && w != a[0] && d[v] == -1)cotl++;

u == 0表示当先访问的是根节点(因为你做邻接表当然都是以0开头,自然用0做根节点,注意这里虽然用了DFS形成树,但本质上还是一个图,所以根结点的选择对结果并没有影响)
w != a[0] 表示当前访问的分支,不是根结点的第一个分支,如下图(a)有根结点有两个分支 ,(b)只有一个分支。
在这里插入图片描述
d[v] == -1,表示当前访问结点未被访问过,
总的来说就是,如果根结点不是关节点,那么从他第一个分支开始深度优先遍历时,其他分支上的结点应该都被访问过了,如果没被访问,说明根结点是连接这一分支与第一分支的唯一通道,符合关节点定义。


总结

我其实超级菜,希望大家一起学习,共同进步。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值