图的邻接矩阵求图的出度,入度,可达矩阵,判断强连通,弱连通,单向连通(C++,vs2017)

article/2025/9/25 2:24:47

一、介绍概念

 

1、邻接矩阵

       将一个n个节点的图,转化成一个n*n的矩阵G,G[i][j]表示第i个节点到第j个节点的的权重。

      

      对于上图邻接矩阵为:

      

2、度

      度分为入度和出度:某个节点的入度就是可以通过一条边到达这个节点的节点个数,某个节点的出度就是可以通过一条边到达其它节点的节点个数

      

     在这个图中只有3节点可以到达0节点,0节点可以到达1节点和2节点,所以0节点的入度为:1,出度为2

3、可达矩阵:

     可达矩阵是一个n*n的矩阵rechG,如果节点i可以到达节点j,那么rechG[i][j]=1,反之,则为rechG[i][j]=0;可以采取这种计算方式:

        tmpG=G+G^{^{2}}+G^{^{3}}+\cdots +G^{^{n}}

       rechG[i][j]=\left\{\begin{matrix} 1, tmpG[i][j]!=0 & \\ 0, tmpG[i][j]==0& \end{matrix}\right.

4、连通(有向图)

      (1)强连通:当每个节点都可以到达其它节点的时候就是强连通

      如图:(下图就是一个强连通图)

      

      (2)单向连通:只要对任意两个节点:节点i, 节点j,如果i可以到达j(条件1),或者j可以到达i(条件2),只要满足一个条件,就是单向连通图。

       如果:(下图是一个单向连通图)

      

         (3)弱连通:将有向图转化成无向图的时候,如果这个无向图是强连通,那么原图是弱连通。

           结论:单向连通图一定是弱通图,弱连通图不一定是单向连通图

           如下图:是弱连通图,单不是单向连通图

           

二、实现思路(邻接矩阵)

1、出度和入度

     出度邻接矩阵第i行的和(主对角线为0)就是第i个节点的出度

     入度邻接矩阵第j列的和(主对角线为0)就是第j个节点的入度

如下是代码:graphic[i][j]是邻接矩阵:

/*输出有序顶点对,以及每个顶点的入度和出度*/
void display_degree()
{
    cout << "\n每个顶点的入度和出度如下:" << endl;
    for (int i = 0; i < vernum; i++)
    {
        cout << "第" << i << "个顶点的入度和出度:";
        int intoDegree = 0;  //入度
        int outDegree = 0;   //出度
        for (int j = 0; j < vernum; j++)
        {
            if (graphic[j][i] != 0&&i!=j)
                intoDegree++;  
            if (graphic[i][j] != 0&&i!=j)
                outDegree++;
        }
        cout << intoDegree << "\t" << outDegree << endl;
    }
}

2、可达矩阵:

可达矩阵计算方式很多,下面给出其中一种解法:rechG是计算的可达矩阵

     

        tmpG=G+G^{^{2}}+G^{^{3}}+\cdots +G^{^{n}}

       rechG[i][j]=\left\{\begin{matrix} 1, tmpG[i][j]!=0 & \\ 0, tmpG[i][j]==0& \end{matrix}\right.

代码如下:

/*矩阵乘法*/
void matrix_multi(int A[][MAX],int B[][MAX])
{
    //乘法的最后结果保存再A矩阵中
    int result[MAX][MAX];
    memset(result, 0, sizeof(result));
    for (int i = 0; i < vernum; i++)
    {
        for (int j = 0; j < vernum; j++)
        {
            for (int v = 0; v < vernum; v++)
            {
                result[i][j] += A[i][v] * B[v][j];
            }
        }
    }
    //拷贝到A中
    for (int i = 0; i < vernum; i++)
    {
        for (int j = 0; j < vernum; j++)
        {
            A[i][j] = result[i][j];
        }
    }

}

/*求可达矩阵*/
void rechable_matrix()
{
    int tmp_matrix[MAX][MAX];   //可到达矩阵的每一项比如A^i
    for (int i = 0; i < vernum; i++)   //主对角线设置为1
        graphic[i][i] = 1;
    for (int i = 0; i < vernum; i++)
    {
        for (int j = 0; j < vernum; j++)
        {
            tmp_matrix[i][j] = graphic[i][j];
            rech_matrix[i][j] = graphic[i][j];
        }
    }
    for (int i = 1; i < vernum; i++)
    {
        for (int j = 0; j < i; j++)
        {
            matrix_multi(tmp_matrix, graphic);
        }
        //相加
        for (int m = 0; m < vernum; m++)
        {
            for (int n = 0; n < vernum; n++)
            {
                rech_matrix[m][n] = rech_matrix[m][n] + tmp_matrix[m][n];
            }
        }
    }
    cout << "可达矩阵为:" << endl;
    for (int i = 0; i < vernum; i++)
    {
        for (int j = 0; j < vernum; j++)
        {
            if (rech_matrix[i][j] != 0)
                cout << "1" << "\t";
            else
                cout << "0" << "\t";
        }
        cout << endl;
    }
}

3、判断图的连通性

强连通:通过上面计算的可达矩阵,如果所有元素都不为0,就是强连通

单向连通图:如果已经判断不为强连通,计算对于所有i,j的rech_matrix[i][j]不为0(条件1)和rech_matrix[j][i]不为0(条件2),如果条件1和条件2满足其中一个条件,就是单向连通图。

弱连通图:如果不是强连通图,将有向图变成无向图,如果无向图是强连通,那么有向图是弱连通。

三、代码如下

// graphics_judge.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
using namespace std;
#define MAX 100//邻接矩阵的变量
int vernum;    //节点个数
int graphic[MAX][MAX];
int rech_matrix[MAX][MAX]; //可达矩阵/*初始化矩阵*/
void init_graphic();
/*输出有序顶点对,以及每个顶点的入度和出度*/
void display_degree();
/*矩阵乘法*/
void matrix_multi(int A[][MAX], int B[][MAX]);
/*求可达矩阵*/
void rechable_matrix();
/*判断强连通或则若连通:通过可达矩阵判断,强连通返回0,单向连通返回1,否则返回-1*/
int judge_connected_graph();
/*判断是否是弱连通*/
void judge_connected_weakgraph();int main()
{init_graphic();display_degree();rechable_matrix();int flag = judge_connected_graph();if (flag == 0){cout << "输入的图是强连通图" << endl;}else{if (flag == 1)cout << "输入的图是单向连通图" << endl;judge_connected_weakgraph();}return 0;
}/*初始化矩阵*/
void init_graphic()
{cout << "请输入图的节点个数:";cin >> vernum;cout << "请输入一个为" << vernum << "的0,1方正:" << endl;for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){cin >> graphic[i][j];if (i == j)graphic[i][j] = 1;}}
}/*输出有序顶点对,以及每个顶点的入度和出度*/
void display_degree()
{cout << "输出有序顶点对:" << endl;for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){if (graphic[i][j] != 0){cout << "<" << i << "," << j << ">" << "\t";}}}cout << "\n每个顶点的入度和出度如下:" << endl;for (int i = 0; i < vernum; i++){cout << "第" << i << "个顶点的入度和出度:";int intoDegree = 0;  //入度int outDegree = 0;   //出度for (int j = 0; j < vernum; j++){if (graphic[j][i] != 0&&i!=j)intoDegree++;  if (graphic[i][j] != 0&&i!=j)outDegree++;}cout << intoDegree << "\t" << outDegree << endl;}
}/*矩阵乘法*/
void matrix_multi(int A[][MAX],int B[][MAX])
{//乘法的最后结果保存再A矩阵中int result[MAX][MAX];memset(result, 0, sizeof(result));for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){for (int v = 0; v < vernum; v++){result[i][j] += A[i][v] * B[v][j];}}}//拷贝到A中for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){A[i][j] = result[i][j];}}}/*求可达矩阵*/
void rechable_matrix()
{int tmp_matrix[MAX][MAX];   //可到达矩阵的每一项比如A^ifor (int i = 0; i < vernum; i++)   //主对角线设置为1graphic[i][i] = 1;for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){tmp_matrix[i][j] = graphic[i][j];rech_matrix[i][j] = graphic[i][j];}}for (int i = 1; i < vernum; i++){for (int j = 0; j < i; j++){matrix_multi(tmp_matrix, graphic);}//相加for (int m = 0; m < vernum; m++){for (int n = 0; n < vernum; n++){rech_matrix[m][n] = rech_matrix[m][n] + tmp_matrix[m][n];}}}cout << "可达矩阵为:" << endl;for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){if (rech_matrix[i][j] != 0)cout << "1" << "\t";elsecout << "0" << "\t";}cout << endl;}
}int judge_connected_graph()
{int flag_connected = 0;  //强连通为0,单向连通为1,否则为-1/*判断强连通和单向连通*/for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){if (rech_matrix[i][j] == 0)flag_connected = 1;}}if (flag_connected == 0)return 0;for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){if (rech_matrix[i][j] == 0 && rech_matrix[j][i] == 0)return -1;}}return 1;
}/*判断是否是弱连通*/
void judge_connected_weakgraph()
{for (int i = 0; i < vernum; i++){for (int j = 0; j < vernum; j++){if (graphic[i][j] != 0){graphic[j][i] = graphic[i][j];}}}cout << "转化成无向图后的可达矩阵为:" << endl;rechable_matrix();if (judge_connected_graph() == 0)cout << "可以发现原图是个弱连通图" << endl;elsecout << "可以发现原图不是一个弱连通图" << endl;
}

 

 

 

 

 

 

 

 

    

 

 


http://chatgpt.dhexx.cn/article/ojoAlghM.shtml

相关文章

【离散数学】图论 第七章(3) 图的矩阵表示(邻接矩阵、可达矩阵、传递闭包求解算法)

本文属于「离散数学」系列文章之一。这一系列着重于离散数学的学习和应用。由于内容随时可能发生更新变动&#xff0c;欢迎关注和收藏离散数学系列文章汇总目录一文以作备忘。此外&#xff0c;在本系列学习文章中&#xff0c;为了透彻理解数学知识&#xff0c;本人参考了诸多博…

硬盘的存储原理和内部架构

首先&#xff0c;让我们看一下硬盘的发展史&#xff1a; 1956年9月13日&#xff0c;IBM的IBM 350 RAMAC(Random Access Method of Accounting and Control)是现代硬盘的雏形&#xff0c;整个硬盘需要50个直径为24英寸表面涂有磁浆的盘片&#xff0c;它相当于两个冰箱的体积&…

硬盘结构与工作原理

一、硬盘的接口 接口种类&#xff1a; ATA(Advanced Technology Attachment)(IDE):速度最大可达133MB/S; SATA(Serial ATA):速度最大可达300MB/S SCSI(Small Computer System Interface):转速最大可达15000rpm SAS(Serial Attachment SCSI):速度最大可达6GB/S 二、硬盘的物理结…

硬盘的种类、区别、运行原理

硬盘是电脑主要的储存媒介之一&#xff0c;由一个或者多个铝制或者玻璃制的碟片组成。碟片外覆盖有铁磁性材料。 硬盘的种类可分为&#xff1a; 1、固态硬盘&#xff08;SSD&#xff09;&#xff0c;采用闪存颗粒来储存&#xff1b; 2、机械硬盘&#xff08;HDD&#xff09;&a…

硬件(磁盘):机械硬盘内部硬件结构和工作原理详解

从理解磁盘IO开始 主轴让磁盘盘片转动&#xff0c;然后传动手臂可伸展让读取头在盘片上进行读写操作。每个盘片有两面&#xff0c;都可记录信息&#xff0c;所以一张盘片对应着两个磁头。 磁盘物理结构如下图: 硬盘的外部物理结构 一般硬盘正面贴有产品标签&#xff0c;主要…

硬盘的读写原理详解

硬盘的种类主要是SCSI 、IDE 、以及现在流行的SATA等&#xff1b;任何一种硬盘的生产都要一定的标准&#xff1b;随着相应的标准的升级&#xff0c;硬盘生产技术也在升级&#xff1b;比如 SCSI标准已经经历了SCSI-1 、SCSI-2、SCSI-3&#xff1b;其中目前咱们经常在服务器网站看…

磁盘存储原理

最近学习linux内核源码&#xff0c;读到操作系统boot引导相关内容时&#xff0c;对于磁盘相关原理介绍引起我的兴趣。阅读相关资料后&#xff0c;对磁盘工作原理做一个总结&#xff0c;参考资料为深入理解计算机系统&#xff08;CSAPP)。 磁盘是广泛应用的数据存储设备&#x…

[硬件] 简单介绍磁盘结构及工作原理

一、前言 最近学习&#xff24;&#xff2f;&#xff33;下的汇编语言用到了很多与硬件相关的指令&#xff0c;比如上一期写的int 13h&#xff08;直接磁盘服务&#xff09;&#xff0c;其中接口参数中就有驱动器号&#xff0c;磁头&#xff0c;磁道&#xff0c;扇区的概念&am…

机械硬盘的存储结构及原理

本文转载自:https://blog.csdn.net/u013125075/article/details/86576640 硬盘是电脑主要的存储媒介之一。根据硬盘的读写方式和存储方式不同&#xff0c;当前主流的硬盘可以分为固态硬盘&#xff08;SSD硬盘&#xff09;、机械硬盘&#xff08;HDD 硬盘&#xff09;两种。由于…

硬盘技术原理

**传统硬盘** 所有机械硬盘的原理相同。盘片被磁性材料覆盖&#xff0c;盘片上的磁性粒子被极化以表示一个二进制信息单元&#xff08;或比特&#xff09;。使用磁性材料来存储数据历史很久了&#xff0c;这种方式相对便宜&#xff0c;因此相对于其它存储技术而言&#xff0c;这…

机械硬盘原理介绍

硬盘结构及工作原理 目录&#xff1a; 硬盘结构 概念&#xff1a;盘面、柱面、磁道、扇区、簇 盘面 磁道 扇区 柱面 簇 硬盘读写数据的过程 SMR叠瓦式硬盘 其他硬盘知识 硬盘发展历史 硬盘结构及工作原理 硬盘结构 经过封装后的硬盘&#xff0c;对我们一般呈现出如下的样子…

机械硬盘原理

本篇参考自&#xff1a; https://zhuanlan.zhihu.com/p/89505052 https://blog.csdn.net/li_wen01/article/details/80221182 磁盘存储器原理介绍&#xff1a; 为了了解磁盘的运行原理&#xff0c;先上一些图来展示机械硬盘的构造和运行状态 可以看见&#xff0c;硬盘拆开…

硬盘的读写原理

硬盘的种类主要是SCSI 、IDE 、以及现在流行的SATA等&#xff1b;任何一种硬盘的生产都要一定的标准&#xff1b;随着相应的标准的升级&#xff0c;硬盘生产技术也在升级&#xff1b;比如 SCSI标准已经经历了SCSI-1 、SCSI-2、SCSI-3&#xff1b;其中目前咱们经常在服务器网站看…

※ 将一个txt文档按\n格式分割成多个txt

※ 将一个txt文档按\n格式分割成多个txt 原始文档格式为&#xff1a; # -*- coding: utf-8 -*- """ Created on Mon May 20 15:33:23 2019author: sun """# 读取txt文件 import retext open(聚类4类.txt,"r", encodingUTF-8).read()…

切分pdf并提取内容

pdf里面包含多篇报告&#xff0c;报告以文章编号结尾&#xff0c;部分存在文章连接 。目的提取报告的标题&#xff0c;版号&#xff0c;版面&#xff0c;作者&#xff0c;文章编号&#xff0c;原文连接&#xff0c;以及文章主体部分大概文字 代码如下&#xff1a; blocks&#…

Python3.6 word批量转换为txt提取

1.流程&#xff1a;批量读取文件夹下文件&#xff0c;批量转换word为txt文件&#xff0c;读取txt文件内容 2.word文件放入&#xff1a; D:\jianli &#xff0c;文件夹下放入 一个word文件 代码如下&#xff1a; 注意导入库 mport os import re import sys import psutil i…

txt文件合并

txt文件合并 1、将要合并的txt文件均放到一个文件夹下。 2、使用WinR组合键或双击桌面左下角的操作系统选择运行打开运行窗口&#xff0c;输入cmd&#xff0c;点击确定进入命令行窗口。 3、输入文件夹地址&#xff0c;回车。&#xff08;注意&#xff1a;直接复制的路径带引号…

批量将 txt 记事本文件按照固定行数拆分成单个独立的 txt 小文件

概要&#xff1a;记事本文件格式是我们经常使用的格式&#xff0c;我们都知道有些记事本 txt 文件都有很多行&#xff0c;有时候我们需要将这些有很多行的 txt 记事本文件按照固定的行数进行拆分。这个时候该怎么办呢&#xff1f;有没有一种简单的方法&#xff0c;能够批量的将…

txt转azw3软件在线转换有哪些?快把这些软件收好

azw3是一种Kindle使用的电子书格式&#xff0c;目前电脑上大部分电子书都是以txt格式存储的&#xff0c;我们如果想要在Kindle上阅读电子书的话&#xff0c;就需要先将txt转换成azw3格式。那你们知道txt转azw3转换软件哪个好吗&#xff1f;想要进行txt格式转换的小伙伴&#xf…