当前位置:网站首页>图论入门——建图
图论入门——建图
2022-04-23 06:21:00 【Zimba_】
背景:
本来以前学过的东西都懒得写了,不过小徒弟学图论好像碰到瓶颈了,就写一篇大致讲一下。
概念:
首先,我们要了解图的定义。
什么是图?
一张图 G G G由两个集合组成的二元组,点集 V V V和边集 E E E。即 G = ( V , E ) G=(V,E) G=(V,E)。
边就是连接点和点之间的关系,分成有向边和无向边两种。
无向图就是都是无向边的图。
有向图就是有向边组成的图。
具体题目中,边和点可能由权值,也就是点权和边权。
路径是一个点到另一个点经过的边的序列。
简单路径指没有经过重复边的路径。
环,也叫回路,指的是一个点经过一条简单路径回到自身。
度一个点连的边的数量。
出度一个点连的出边的数量。
入度一个点连的入边的数量。
重边是两条起点和终点相同的边。
自环是自己连到自己的边,理论上也叫环。
因为这两个东西的存在比较奇怪,有时候题目里会特意注明不存在重边和自环,如果没有的话就要小心了。
还有竞赛中常见的一种图有向无环图(Directed Acyclic Graph),顾名思义,就是有方向的没有环的图(都是有向边,没有无向边)。俗称DAG。
再常见的一种图,树。题目太常见,这里入门就不介绍了。由多棵树组成的图叫森林,名字很形象了。
还有二分图,一个图是二分图有一个重要的等价条件是这个图没有奇环。(奇环:奇数个点构成的环)
还有一些会出到题目的高级图:弦图,基环树(基环内向树和基环外向树),仙人掌(圆方树)。
也许还有……
建图:
既然知道了图,我们需要学习怎么在代码中构建一张图。
那么构建一张图需要有什么操作呢。
1. 1. 1.加边:我们需要在图中添加一条边。
2. 2. 2.遍历一个点连接的边。
用数组把所有边存起来的办法就不说了。
这里介绍三种我常用的建图方式。
一、矩阵存图
就是用一个二维数组,行列都代表点,矩阵内的值表示边权。
那么解决上面两个问题,我们要添加一条边 ( a , b ) (a,b) (a,b),边权为 w w w,那么就 t u [ a ] [ b ] = w tu[a][b]=w tu[a][b]=w。(这里不考虑重边)
如果是无向边,那其实就是添加两条有向边, t u [ a ] [ b ] = t u [ b ] [ a ] = w tu[a][b]=tu[b][a]=w tu[a][b]=tu[b][a]=w。
那么另一个问题,怎么去遍历一个点 x x x连的边,其实就是第 x x x行扫过去。
int tu[maxn][maxn];//图
memset(tu,0,sizeof(tu));//初始化图
tu[a][b]=w;//添加一条a到b的边权为w的有向边
tu[a][b]=tu[a][b]=w;//添加一条a到b的边权为w的无向边
//遍历点x连的边
for(int i=1;i<=n;i++)if(i!=x&&tu[x][i]!=0)
{
printf("点x到点%d,边权为%d的边\n",i,tu[x][i]);
}
这样建图有两个缺陷。一是内存占用是 o ( n 2 ) o(n^{2}) o(n2),当点数为 1 0 5 10^5 105的时候就开不下了。二是我们遍历一个点连的边复杂度是 o ( n ) o(n) o(n),但这个点连的边可能不足 n n n,造成了浪费。
当然也是有好处的,比如删边和加边可以o(1),也可以快速查找某两个点之间的边。
为了有时候对上面两个缺陷的需要,就有了后面两种建图的方式。
二、vector存图(邻接表存图)
数据结构课里的邻接表存图还是老老实实地写链表,这里只介绍竞赛里常用的。
大概介绍一下邻接表存图,我们对每一个点建一个点结点 [ a ] [a] [a],当我们要加一条有向边(a,b)的时候,就把它接在 [ a ] [a] [a]的后面。(如果是无向边,那就 [ a ] [a] [a]和 [ b ] [b] [b]后面都接一个,即加入有向边(a,b)和(b,a))
比如加入有向边 ( a , b ) (a,b) (a,b), ( a , c ) (a,c) (a,c), ( a , d ) (a,d) (a,d)后, [ a ] [a] [a]的情况如下。
[ a ] − > ( b ) − > ( c ) − > ( d ) [a]->(b)->(c)->(d) [a]−>(b)−>(c)−>(d)
( ) () ()内的表示边的信息,如果还有边权,就变成下面这样了。
[ a ] − > ( b , w b ) − > ( c , w c ) − > ( d , w d ) [a]->(b,wb)->(c,wc)->(d,wd) [a]−>(b,wb)−>(c,wc)−>(d,wd)
我们放到 v e c t o r vector vector里面,就是 v [ a ] = { ( b , w b ) , ( c , w c ) , ( d , w d ) } v[a]=\{(b,wb),(c,wc),(d,wd)\} v[a]={
(b,wb),(c,wc),(d,wd)}。
或者不想写结构体,也可以用两个 v e c t o r vector vector,
v [ a ] = { b , c , d } v[a]=\{b,c,d\} v[a]={
b,c,d}
g [ a ] = { w b , w c , w d } g[a]=\{wb,wc,wd\} g[a]={
wb,wc,wd}
上下一一出点和边权对应就行了。
//第一种写法,用结构体
struct E
{
int to,w;
};
vector<E>v[maxn];//图
for(int i=0;i<maxn;i++)v[i].clear();//初始化图
v[a].push_back(E{
b,w});//添加一条a到b的边权为w的有向边
//添加一条a到b的边权为w的无向边
v[a].push_back(E{
b,w});
v[b].push_back(E{
a,w});
//遍历点x的连的出边
for(int i=0;i<v[x].size();i++)
{
int to=v[x][i].to,w=v[x][i].w;
printf("点x到点%d,边权为%d的边\n",to,w);
}
//第二种写法,不用结构体
vector<int>v[maxn],g[maxn];//图
for(int i=0;i<maxn;i++)v[i].clear(),g[i].clear();//初始化图
v[a].push_back(b);//添加一条a到b的边权为w的有向边
g[a].push_back(w);
//添加一条a到b的边权为w的无向边
v[a].push_back(b);
g[a].push_back(w);
v[b].push_back(a);
g[b].push_back(w);
//遍历点x的连的出边
for(int i=0;i<v[x].size();i++)
{
int to=v[x][i],w=g[x][i];
printf("点x到点%d,边权为%d的边\n",to,w);
}
三、链式前向星
存图方式和前面的一样,都是接在后面。
不过这个是用链表实现,这个写的时候链表也不用指针,用下标索引实现。
具体理解看代码吧。
struct
{
int to,w,next;
}edge[maxm];
int head[maxn],tot;//图
void init()//初始化图
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int a,int b,int w)//添加一条a到b边权为w的有向边,无向边就正反各加一次
{
edge[tot].to=b;
edge[tot].w=w;
edge[tot].next=head[a];
head[a]=tot++;
}
//遍历点x的连的出边
for(int i=head[x];i!=-1;i=edge[i].next)
{
int to=edge[i].to,w=edge[i].w;
printf("点x到点%d,边权为%d的边\n",to,w);
}
讲完了。
版权声明
本文为[Zimba_]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43785386/article/details/108874018
边栏推荐
- 通用型冒泡、选择、插入、希尔、快速排序的代码实现
- Patrol inspection intercom communication system in power industry
- Flexible blind patch of ad hoc network | Beifeng oil and gas field survey solution
- Meishe technology launches professional video editing solution for desktop -- Meiying PC version
- pytorch:关于GradReverseLayer实现的一个坑
- ESP32学习-向工程项目添加文件夹
- javscript获取文件真实后缀名
- Intelligent communication solution of Hainan Phoenix Airport
- Meishe helps Baidu "Duka editing" to make knowledge creation easier
- PyTorch 22. Pytorch common code snippet collection
猜你喜欢
随机推荐
LATEX公式注意事项
Beifeng communication helps Zhanjiang fire brigade build PDT wireless communication system
(一)OpenPAI jupyter jupyterhub jupyterlab 方案比较
PyTorch 11. Regularization
两个线程交互打印奇偶数字
H5案例开发
[hdu6868]Absolute Math(推式子+莫比乌斯反演)
Jiangning hospital DMR system solution
el-date-picker中自定义快捷选项picker-options,动态设置禁用日期
Machine vision series (02) -- tensorflow2 3 + win10 + GPU installation
Emergency communication system for flood control and disaster relief
PyTorch 22. Pytorch common code snippet collection
P1390 公约数的和(莫比乌斯反演)
Mysql持久性的实现
Emergency medical communication solution | mesh wireless ad hoc network system
go iris框架实现多服务Demo:通过(监听8083端口的)服务1中的接口启动(监听8084端口的)服务2
Lead the industry trend with intelligent production! American camera intelligent video production platform unveiled at 2021 world Ultra HD Video Industry Development Conference
通用型冒泡、选择、插入、希尔、快速排序的代码实现
记录一些npm 有关的问题(杂乱记录)
Wireless communication system for large-scale sports events