图的割点(邻接矩阵实现)

/*

Name: 图的割点(邻接矩阵)

Copyright:

Author: 巧若拙

Date: 21-11-14 20:34

Description:

在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合。

求割点与桥的算法是R.Tarjan发明的。对图深度优先搜索,定义DFS(u)为u在搜索树(以下简称为树)中被遍历到的次序号(等价于时间戳)。

定义Low(u)为u或u的子树中能通过非父子边追溯到的最早的节点,即DFS序号最小的节点的序号。根据定义,则有:

Low(u)=Min { DFS(u) ,DFS(v)},其中 (u,v)为后向边(返祖边) 等价于 DFS(v)<DFS(u)且v不为u的父亲节点 Low(v) (u,v)为树枝边(父子边)

一个顶点u是割点,当且仅当满足(1)或(2) :

(1) u为树根,且u有多于一个子树。

(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)。

本文用邻接矩阵存储图的信息,实现了递归和非递归两种算法。

*/

#include<stdio.h>

#include<stdlib.h>

#define MAXN 26   //最大变量(顶点)数量

typedef char VertexType; //顶点类型由用户自定义

typedef int EdgeType; //边上的权值类型由用户自定义

typedef struct EdgeNode{ //边表结点

int adjvex;  //邻接点域,存储该顶点对应的下标

// EdgeType weight; //权值,对于非网图可以不需要

struct EdgeNode *next; //链域,指向下一个邻接点

} EdgeNode;

typedef struct VertexNode{ //顶点表结点

VertexType data; //顶点域,存储顶点信息

EdgeNode *firstEdge; //边表头指针

} VertexNode;

int flag[MAXN] = {0}; //存储顶点是否为割点

int num[MAXN] = {0}; //存储顶点的时间戳信息

int low[MAXN] = {0}; //存储顶点的最小时间戳信息

int index = 0; //用来进行时间戳的递增

void CreateGraph(VertexNode *GL, int n, int m);//创建一个图

void PrintGraph(VertexNode *GL, int n, int m);//输出图

void CutPoint_DFS(VertexNode *GL, int root, int cur, int father);//采用深度优先搜索寻找割点(递归算法)

void CutPoint(VertexNode *GL, int root, int n);//采用深度优先搜索寻找割点(非递归算法)

int main()

{

int i, m, n;

VertexNode GL[MAXN];

printf("请输入顶点数量和边数量:\n");

scanf("%d%d", &n, &m);

CreateGraph(GL, n, m);//创建一个图

PrintGraph(GL, n, m);//输出图

// CutPoint_DFS(GL, 0, 0, 0);//从0号顶点开始深度优先搜索寻找割点(递归算法)

CutPoint(GL, 0, n);//采用深度优先搜索寻找割点(非递归算法)

printf("\n割点为:");

for (i=0; i<n; i++)//输出所有割点

{

if (flag[i] == 1)

printf("%d ", i);

}

printf("\n");

return 0;

}

void CreateGraph(VertexNode *GL, int n, int m)//创建一个图

{

int i, u, v;

EdgeNode *e;

for (i=0; i<n; i++)//初始化图

{

GL[i].data = i;

GL[i].firstEdge = NULL;

num[i] = low[i] = flag[i] = 0;

}

for (i=0; i<m; i++) //读入边信息(注意是无向图)

{

scanf("%d%d", &u, &v);

e = (EdgeNode*)malloc(sizeof(EdgeNode)); //采用头插法插入边表结点

if (!e)

{

puts("Error");

exit(1);

}

e->next = GL[u].firstEdge;

GL[u].firstEdge = e;

e->adjvex = v;

e = (EdgeNode*)malloc(sizeof(EdgeNode)); //采用头插法插入边表结点

if (!e)

{

puts("Error");

exit(1);

}

e->next = GL[v].firstEdge;

GL[v].firstEdge = e;

e->adjvex = u;

}

}

void PrintGraph(VertexNode *GL, int n, int m)//输出图

{

int i, j;

EdgeNode *e;

for (i=0; i<n; i++)

{

printf("%d: ", i);

e = GL[i].firstEdge;

while (e)

{

printf("<%d, %d>, ", i, e->adjvex);

e = e->next;

}

printf("\n");

}

printf("\n");

}

void CutPoint_DFS(VertexNode *GL, int root, int cur, int father)//采用深度优先搜索寻找割点(递归算法)

{

int child = 0;

EdgeNode *e = GL[cur].firstEdge;

num[cur] = low[cur] = ++index;

while (e)

{

if (num[e->adjvex] == 0) //新结点做儿子

{

child++;

CutPoint_DFS(GL, root, e->adjvex, cur);

low[cur] = (low[cur] < low[e->adjvex]) ? low[cur] : low[e->adjvex];//取最小值

if ((cur != root && num[cur] <= low[e->adjvex])

|| (cur == root && child == 2))

{

flag[cur] = 1;

}

}

else if (e->adjvex != father) //与旁系祖先有连接,其实也可以不加这个限制条件,因为如果父亲是自己则low[cur]值不变

{

low[cur] = (low[cur] < num[e->adjvex]) ? low[cur] : num[e->adjvex];//取最小值

}

e = e->next;

}

}

void CutPoint(VertexNode *GL, int root, int n)//采用深度优先搜索寻找割点(非递归算法)

{

int Stack[MAXN]; //用来存储当前被处理顶点的栈

EdgeNode *SF[MAXN], *e;

int child[MAXN] = {0}; //存储顶点的儿子数量

int u, v, top = 0;

for (u=0; u<n; u++)//初始化SF

SF[u] = GL[u].firstEdge;

Stack[top] = root;

num[root] = low[root] = ++index;

while (top >= 0)

{

e = SF[Stack[top]];

if (e)

{

SF[Stack[top]] = e->next; //指向下一条边

if (num[e->adjvex] == 0)

{

child[Stack[top]]++;

Stack[++top] = e->adjvex;

low[e->adjvex] = num[e->adjvex] = ++index;

}

else

{

low[Stack[top]] = (low[Stack[top]] < num[e->adjvex]) ? low[Stack[top]] : num[e->adjvex];//取最小值

}

}

else

{

if (top > 0)

{

u = Stack[top-1];

v = Stack[top];

low[u] = (low[u] < low[v]) ? low[u] : low[v];

if ((u != root && low[v] >= num[u])

|| (u == root && child[u] == 2))

{

flag[u] = 1;

}

}

top--;

}

}

}

时间: 2024-10-12 21:33:22

图的割点(邻接矩阵实现)的相关文章

图的割点 | | jzoj【P1230】 | | gdoi | |备用交换机

写在前面:我真的不知道图的割点是什么.... 看见ftp图论专题里面有个dfnlow的一个文档,于是怀着好奇的心情打开了这个罪恶的word文档,,然后就开始漫长的P1230的征讨战.... 图的割点是这样的: path1=暴力 枚举每一个点,如果去掉这个点就可以使图断开,那么这个点就是割点(时间复杂度O(N(N+M))) path2=tarjan 从任意一个点开始遍历,记录遍历的顺序,然后对正在遍历的点进行一次深度优先遍历,但是此次遍历不允许经过这个点,看看还能不能回到前一个点 这时候我们就可以

数据结构:图的实现--邻接矩阵

图结构的邻接矩阵实现 为了表现图中顶点之间的关联,我们可以使用邻接矩阵来实现图结构.所谓的邻接矩阵,就是一个反应边与边之间联系的二维数组.这个二维数组我们用matrix[numV][numV]表示,其中numV是顶点数. 对于无权图 若顶点Vi和Vj之间有边,则matrix[Vi][Vj]=1;否则matrix[Vi][Vj]=0. 对于有权图 若顶点Vi和Vj之间有边,且权值为weight,则matrix[Vi][Vj]=weight;否则matrix[Vi][Vj]=0或MAXWEIGHT(

图的割点、桥与双连通分支

原文地址:图的割点.桥与双连通分支 [点连通度与边连通度] 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合.一个图的点连通度的定义为,最小割点集合中的顶点数. 类似的,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合.一个图的边连通度的定义为,最小割边集合中的边数. [双连通图.割点与桥] 如果一个无向连通图的点连通度大于1,则称该图是点双连通的(point biconne

图的割点(边表集实现)

/* Name: 图的割点(边表集实现) Copyright: Author: 巧若拙 Date: 20-11-14 21:17 Description: 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合. 求割点与桥的算法是R.Tarjan发明的.对图深度优先搜索,定义DFS(u)为u在搜索树(以下简称为树)中被遍历到的次序号(等价于时间戳). 定义Low(u)为u或u的子树中能通过非父子边追溯到的最早的

关于图的割点

在一个无向图中,若删除某一个节点,使得图分成若干个不相联通的子图,那么,这个节点就是图的割点.就像下图所示: 节点1.节点3和节点4,都是这个图的割点.为什么呢?你想啊,把节点1.节点3和节点4遮住,会怎么样?节点2永远也没法去到6 5 8 7 那些,同理,遮住节点4后,7,8也没法去到6 5 了.这样,就形成了一个个独立子图了. 那么,我们怎么知道这个点,就是割点呢? ①.用两个DFS,删除某个节点后,对其后面的节点进行DFS,如果在[不同过该节点]的情况下,不能回到以前的节点,那么,被删除的

【转载】图的割点、桥与双连通分支

[点连通度与边连通度] 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合.一个图的点连通度的定义为,最小割点集合中的顶点数. 类似的,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合.一个图的边连通度的定义为,最小割边集合中的边数. [双连通图.割点与桥] 如果一个无向连通图的点连通度大于1,则称该图是点双连通的(point biconnected),简称双连通或重连通.一个

【转】图的割点、桥与双连通分支

原文地址:https://www.byvoid.com/blog/biconnect 图的割点.桥与双连通分支 [点连通度与边连通度] 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合.一个图的点连通度的定义为,最小割点集合中的顶点数. 类似的,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合.一个图的边连通度的定义为,最小割边集合中的边数. [双连通图.割点与桥] 如果一个

Tarjan算法:求解图的割点与桥(割边)

简介: 割边和割点的定义仅限于无向图中.我们可以通过定义以蛮力方式求解出无向图的所有割点和割边,但这样的求解方式效率低.Tarjan提出了一种快速求解的方式,通过一次DFS就求解出图中所有的割点和割边. 欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 割点与桥(割边)的定义 在无向图中才有割边和割点的定义 割点:无向连通图中,去掉一个顶点及和它相邻的所有边,图中的连通分量数增加,则该顶点称为割点. 桥(割边):无向联通图中,去

图的割点算法、图的割边算法

割点算法 • 在一个无向连通图中,如果删除某个顶点后,图不再连通(即任意两点之间不能相互到达),我们称这样的顶点为割点(或者称割顶). 判断一个顶点是不是割点除了从定义,还可以从DFS(深度优先遍历)的角度出发.我们先通过DFS定义两个概念. 假设DFS中我们从顶点U访问到了顶点V(此时顶点V还未被访问过),那么我们称顶点U为顶点V的父顶点,V为U的孩子顶点.在顶点U之前被访问过的顶点,我们就称之为U的祖先顶点. 显然如果顶点U的所有孩子顶点可以不通过父顶点U而访问到U的祖先顶点,那么说明此时去