离散数学图论部分总结
图论内容总结
前言:
图论这一部分内容可谓离散数学的点睛之笔,离散数学很多堆砌的概念在这章似乎都活过来了(可能是因为我刷算法题的原因),概念之间的联系更加的紧密。
学完图论部分我感觉里面很多的知识点都非常重要,比如顶点度数,握手定理,树,而考点的话除了这些,还有求欧拉回路,最短路径问题,最小生成树(求前缀码)等等。
目录:
- 图的基本概念
- 欧拉图和哈密顿图
- 树
- 代码实现相关算法或证明
Part1:图的基本概念
一.基础概念:
- 无序对和无序积:集合A&B={(a,b)|a∈A,b∈B},(a,b)=(b,a)
- 图:一个序偶<V,E>,V是结点集,E:边集,E中每个元素都有V中的结点对与之对应称之边。
- 零图: G= (VE)中,顶点总数记做|V,变数记做E。如果边数较少,称为稀疏图。一条边也没有的图称为零图。仅有一个顶点的图称为平凡图,平凡图比为零图。
- 无向图:G=
,其中定点V是非空有穷集合,其元素称为顶点;边集E为V&V的多重子集,其元素称为无向边(不限定边的方向),简称边。 - 有向图:D=<V,E>。D的基图:用无向边替代有向边
- 性质:V(G),E(G),V(D),E(D):G和D的顶点集,边集
- n阶图: n个顶点的图
- 零图:E= ∅
- 平凡图:—阶零图。
- 空图:V= ∅
- 顶点和边的关联关系:
设e=(u,v)是无向图G=(V,E)的一条边,称u, v为e的端点,e与u(v)关联,若u≠v,则称e与u(v)关联次数为1;若u=v,则称e为环,此时称e与u的关联次数为2;若w不是e端点,则称e与w的关联此时为0,无边关联的顶点称作孤立点。 - 顶点的度数:
设G=<V,E>为无向图,v∈V,v的度数(度)符号d(v)/deg(v):顶点v关联的边数称为该顶点的度数。若v有环,计算度数d(v)增加2;
有向图的度数:
图示:
-
图论定理-握手定理
任意无向图和有向图的所有顶点度数之和都等于变数的2倍,并且有向图的所有顶点入度之和等于出度之和等于边数 -
多重图和简单图
- 在简单图中,如果有2条或2条以上的边关联同一对顶点,则称这些边为平行边,平行边的条数称为重数。
- 含有平行边的图称为多重图
- 既无平行边也无环的图称为简单图
-
图的同构:
- 定义省略
- G1与G2同构的充要条件:G与G的顶点和边分别存在一一对应且保持关系。
-
完全图:设含n个顶点的简单无(有)向图G=<V,E>中
- n阶无向完全图Kn :每个顶点都与其余顶点相邻的n阶无向简单图
- n阶有向完全图:每对顶点之间均有两条方向相反的有向边的n阶有向简单图
例题:
-
子图与补图:
-
自补图:G与G的补图同构,则称自补图。
-
正则图:无向图G=<V,E>,如果每个顶点的度数都是k,则图G称作k-正则图
-
通路与回路:
- 若通路中所有顶点各异,则称T为初级通路,若初级通路的起点和终点相同时,又称T初级回路。
- 若通路中所有边各异,则称T为简单通路,若简单通路的起点和终点相同时,又称T简单回路
-
无向图的连通性:
- u与v连通:若u与v之间有通路,规定u与自身总连通
- 连通关系:R={<u,v>|u,v ∈V且u~v}是V上的等价关系
- 连通图:任意两点都连通的图,平凡图是连通图
- 连通分支:设无向图G=<V,E>,Vi是V关于顶点之间的连通关系~的一个等价类,称导出子图G[Vi]为G的一个连通分支.G的连通分支数记作p(G).
-
强连通图与弱连通图:在简单有向图G中,任何一对顶点之间至少有一个顶点到另外一个顶点是可达的,则称图是单侧联通的。如果对于图G中任何一对顶点,两者之间两者都是相互可达的,责成这个图是强联通的。如果在图G中,略去边的方向,将他看成无向图后,图是联通的,则称为弱联通的;
-
有向图的连通性:设有向图D=<V,E>
- u可达v:u到v有通路,规定u到自身总是可达的。可达具有自反性和传递性
-
点割:设无向图G=
为联通图,对任意的顶点w∈ V,若删除w及与w相关联的所有边后,无向图不再联通,则w称为割点; -
点割集:设无向图G=
为连通图,若存在点集V1属于V,当删除中所有顶点及与V1顶点相关联的所有边后,图G不再是联通的;而删除了V1的任何真子集V及与V2中顶点先关的所有边后,所得的子图仍是连通图,则称V1是G的一个点割集 -
设无向图G=
为连通图,任意边e ∈ E,若删除e后无向图不再联通,则称e为割边,也成为桥 -
边割集:略
-
** 图的矩阵表示**
- 无向图的关联矩阵:(点与边的关联次数)
性质:图中每一行之和代表顶点度数
- 有向图的关联矩阵:
性质:图中每一行绝对值之和代表顶点度数
- 有向图的邻接矩阵(顶点到顶点的权重或边数):
性质:对角线之和为回路个数,n次幂就意味着回路的距离为n
值不为0则表示可达
例题:
- 无向图的关联矩阵:(点与边的关联次数)
Part2:欧拉图与哈密顿图
一.基本概念:
-
通过图中所有边一次且仅一次的通路称作欧拉通路.
-
通过图中所有边一次且仅一次的回路称作欧拉回路.
-
具有欧拉回路的图称作欧拉图.
-
具有欧拉通路而无欧拉回路的图称作半欧拉图.
-
判定定理:无向图G是欧拉图当且仅当G是连通图且没有奇度顶点.
-
有向图D是欧拉图当且仅当D是强连通图的且每个顶点的入度等于出度.
例题:
-
经过图中所有顶点一次且仅一次的通路称作哈密顿通路.
-
经过图中所有顶点一次且仅一次的回路称作哈密顿回路.
-
具有哈密顿通路但不具有哈密顿回路的图称作半哈密顿图.
-
具有哈密顿回路的图称作哈密顿图.
-
充分条件:
a)设G是n阶无向简单图,若对于G中任意不相邻的顶点u,v,均有d(u) +d(v)≥n-1,则G中存在哈密顿通路.
b)设G是n(n≥3)阶无向简单图,若对于G中任意不相邻的顶点u,v,均有d(u) +d(v)≥n,则G中存在哈密顿回路.满足说明是哈密顿图,不满足则不能说明不是哈密顿图. -
最短路径问题:
Part3:树
- 树:连通且不含回路的图。
ps:平凡图也为树 - 叶:树中度为 1 的结点。
- 枝点(内点):树中度大于 1 的结点。
- 森林:每个连通分支都是树的图。
- 树的性质:
- T连通且无回路;
- T无回路且m = n -1 ;
- T连通且m = n - 1 ;
- T无回路但新增加任何一条边(端点属于T)后有且仅有一个回路;
- T连通,但是删去任何一边后便不再连通;
- T的每一—对结点之间有且仅有一条道路可通。
- 生成树:
- 生成树:给定图G<V,E>,若G的某个生成子图是树,则称其为该图的生成树,记为TG.生成树中的边称为树枝,G不在TG中的边称为弦,称T的所有弦的导出子图为T的余树
- 一个图具有生成树的充分必要条件是该图是连通的
- 求生成树的算法
对于图G<V,E >,|V|=n,|E|=m- 破圈法:每次删除回路中的一条边,删除边的总数量为m -n+1
- 避圈法:每次选取G中一条与已选取的边不构成回路的边,共选取n一1条3.
- 最小生成树
- 生成树中树枝的权值之和记为w(T)
- 连通加权图里的最小生成树是具有边的权之和最小的生成树
- 连通加权图的最小生成树不唯一
- 求最小生成树的算法
- 克鲁斯卡尔(Kruskal)算法:重复选择G中权最小的任一边并且加入到T中不形成简单回路,将其加入到最小生成树T中,重复n一 1次即可(常用)
- 根树:
- 有向树:一个有向图,略去图中所有的有向边的方向得到的无向图如果是一棵树,则称其为有向树
- 有孩子的顶点称为内点,根是内点除非它是图中唯一的顶点,也即入度为1出度大于0的顶点称为内点,内点和根统称为分支点
- 在根树中,从根到任一结点的通路的长度称为该结点的层数。所有顶点的最大层数称为树高。
- 设T为根数,若将T中层数相同的顶点都标定次序,则称T为有序树。
- r叉树:若T每个分支点至多有r个儿子,则称T为r叉树
- 若r叉树是有序的,则称它为r叉有序树
- 若T的每个分支点都恰好有r个儿子,则称T为r叉正则树;又若T是有序的,则称它为r叉正则有序树。
- 若T是r叉正则树,且每个树叶的层数均为树高,则称T为r叉完全正则树。
- 权:树的权指的树中的结点被赋予的一个有某种意义的数,这个数我们就称它为权.
- 带权w1,w2...wi的2叉树中,权最小的2叉树称作最优2叉树。
应用:
最佳前缀码问题:
设7个字母在通信中出现的频率如下:
a:35% b:20%
c:15% d:10%
e:10% f:5%
g:5%
用Huffman算法求得的最佳前缀码传输100 个按上述比例出现的字母组成的字符串需要____bit。
答案:255
Part4:代码实现某些证明:
- 给定一个无向简单图,输出该图的邻接矩阵,根据邻接矩阵输出每个顶点度数,验证握手定理,并判定该图是否为树。
`#include<stdio.h>
`#include<stdlib.h>
`#define MAX 20
typedef int VexType;
typedef VexType Mgraph[MAX][MAX];
Mgraph G1,G2,G3,G4,G7;
int n, e;
int dingdiandushu[MAX];
void reckonMap(Mgraph G5,Mgraph G6) {
for (int i = 1; i <= n; i++)
{
for (int k = 1; k <= n; k++)
{
int sum = 0;
for (int j = 1; j <= n; j++) {
sum += G5[i][j] * G6[j][k];
}
G7[i][k] = sum;
}
}
}
void creat_mg(Mgraph G)
{
int i, j, k;
printf("\n请输入无向图的顶点数和边数,如:6,5:");
scanf("%d %d", &n, &e); //输入顶点数n,边数e
//初始化无向图。
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
//当顶点之间不存在边时,将其对应的矩阵中的值置为1
G[i][j] = 0;
G2[i][j] = 0;
G3[i][j] = 0;
G4[i][j] = 0;
G7[i][j] = 0;
}
}
printf("\n初始化完成!\n");
for (k = 1; k <= e; k++)
{
printf("\n请输入每条边的两个顶点编号,如:2,5:");
scanf("%d %d", &i, &j);
//无向图的矩阵是对称矩阵
G[i][j]++;
G[j][i]++;
G2[i][j]++;
G2[j][i]++;
//有向图只有一方
G3[i][j]++;
G4[i][j]++;
}
printf("\n完成无向图的创建!\n");
}
void output_mg(Mgraph G)
{
int i, j;
printf("\n输出无向图的邻接矩阵!\n");
//像输出二维数组一样输出无向图
for (i = 1; i <= n; i++)
{
printf("\n");
for (j = 1; j <= n; j++)
{
printf("%5d", G[i][j]);
}
}
printf("\n");
printf("\n完成无向图的输出!\n");
}
int main()
{
creat_mg(G1);
output_mg(G1);
//每个顶点的度数
int sum = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dingdiandushu[i] += G1[i][j];
}
printf("顶点%d 度数为%d\n", i, dingdiandushu[i]);
sum += dingdiandushu[i];
}
//验证握手定理
printf("度数之和:%d\n", sum);
printf("边的个数:%d\n", e);
printf("因为度数之和等于边的个数的两倍,故得证握手定理");
//考虑到这是无向图的邻接矩阵,不能通过幂积得到回路情况
//故将无向图转化为有向图,再取n次幂,只要对角线上有大于0的值,说明它就不是树。
output_mg(G3);
sum = 0;//对角线个数和
for (int i = 0; i <= 100; i++)
{
reckonMap(G3, G4);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
G3[i][j] = G7[i][j];
G4[i][j] = G7[i][j];
}
}
for (int i = 1; i <= n; i++) {
sum += G7[i][i];
}
}
if (sum == 0&&n==e+1) {
printf("因为无向图中没有回路,且顶点数等于边数+1,所以该图为树");
}
else
printf("该图非树");
}
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现