图论基础
基本概念:
一、什么是图?
很简单,点用边连起来就叫做图,
严格意义上讲,图是一种数据结构,定义为:graph=(V,E)。
V是一个非空有限集合,代表顶点(结点),E代表边的集合。
二、图的一些定义和概念
(a)有向图:图的边有方向,只能按箭头方向从一点到另一点。(a)就是一个有向图。
(b)无向图:图的边没有方向,可以双向。(b)就是一个无向图。
结点的度:无向图中与结点相连的边的数目,称为结点的度。
结点的入度:在有向图中,以这个结点为终点的有向边的数目。
结点的出度:在有向图中,以这个结点为起点的有向边的数目。
权值:边的“费用”。
连通:如果图中结点U,V之间存在一条从U通过若干条边、点到达V的通路,则称U、V 是连通的。
回路:起点和终点相同的路径,称为回路,或“环”。
完全图:一个n 阶的完全无向图含有n(n-1)/2 条边;一个n 阶的完全有向图含有n(n-1)条边;
稠密图:一个边数接近完全图的图。
稀疏图:一个边数远远少于完全图的图。
图的存储结构
1.邻接矩阵
下面是建立图的邻接矩阵的参考程序段:
#include<iostream>
using namespace std;
int i,j,k,e,n;
double g[101][101];
double w;
int main()
{
int i,j;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
g[i][j] = 0x7fffffff(赋一个超大值); //初始化,对于不带权的图
g[i][j]=0,表示没有边连通。这里用0x7fffffff代替无穷大。
cin >> e;
for (k = 1; k <= e; k++)
{
cin >> i >> j >> w; //读入两个顶点序号及权值
g[i][j] = w; //对于不带权的图g[i][j]=1
g[j][i] = w; //无向图的对称性,如果是有向图则不要有这句
}
return 0;
}
初始化数组大可不必使用两重for循环。如果是int数组,采用memset(g, 0x7f, sizeof(g))可全部初始化为一个很大的数(略小于0x7fffffff),使用memset(g, 0, sizeof(g)),全部清为0,使用memset(g, 0xaf, sizeof(g)),全部初始化为一个很小的数。double数组,采用memset(g,127,sizeof(g));可全部初始化为一个很大的数1.38*10306,使用memset(g, 0, sizeof(g))全部清为0。
2.数组模拟邻接表(链式前向星)
啊,我太懒了,看卷王写的吧
戳这里
要加权值的话就加一句 e[cnt].w=w;
图的遍历
从图中某一顶点出发系统地访问图中所有顶点,使每个顶点恰好被访问一次,这种运算操作被称为图的遍历。为了避免重复访问某个顶点,可以设一个标志数组vis[i],未访问时值为false,访问一次后就改为true。
图的遍历分为深度优先遍历和广度优先遍历两种方法,两者的时间效率都是O(n)。
DFS
void dfs(int t){
vis[t] = 1;
// printf("%d ",t);
for( int i=head[t];i;i=e[i].next){
if(!vis[e[i].v]) dfs(e[i].v);
}
}
BFS
void bfs(int t){
queue <int> q ;
int u;
q.push(t);
while(!q.empty()){
u=q.front();
q.pop();
if(vis[u]) continue;
vis[u]=1;
// printf("%d ",u);
for(int i=head[u];i;i=e[i].next){
q.push(e[i].v);
}
}
}
欧拉路(一笔画问题)
如果一个图存在一笔画,则一笔画的路径叫做欧拉路,如果最后又回到起点,那这个路径叫做欧拉回路。
我们定义奇点是指跟这个点相连的边数目有奇数个的点。对于能够一笔画的图,我们有以下两个定理。
定理1:存在欧拉路的条件:图是连通的,有且只有2个奇点。
定理2:存在欧拉回路的条件:图是连通的,有0个奇点。
两个定理的正确性是显而易见的,既然每条边都要经过一次,那么对于欧拉路,除了起点和终点外,每个点如果进入了一次,显然一定要出去一次,显然是偶点。对于欧拉回路,每个点进入和出去次数一定都是相等的,显然没有奇点。
求欧拉路的算法很简单,使用深度优先遍历即可。
根据一笔画的两个定理,如果寻找欧拉回路,对任意一个点执行深度优先遍历;找欧拉路,则对一个奇点执行DFS,时间复杂度为O(m+n),m为边数,n是点数。
哈密尔顿图
欧拉通路是指不重复地走过所有路径,而哈密尔顿通路是指不重复地走过所有的点。
哈密尔顿环是指不重复地走过所有的点,并且最后还能回到起点的回路。
本文作者:Gym_nastics
本文链接:https://www.cnblogs.com/BlackDan/p/15257590.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)