题外话
老师这回又叫我们来写博客了,写一写邻接矩阵。
注意:本博客仅讨论无向无权图
想必上一个博客已经让大家了解了图的基本知识了
没来得及看的在csdn上随便搜一篇来看因为我都是摘录百度百科的
比如这篇博客图的定义、读入与储存_dyx916_的博客-CSDN博客
咳咳,接下来正式进入正题:
邻接矩阵
首先看一下定义:
以下摘自百度百科
邻接矩阵(Adjacency Matrix)是表示顶点之间相邻关系的矩阵。设 G = ( V , E ) G=(V,E) G=(V,E)是一个图,其中 V = v 1 , v 2 , … , v n V={v1,v2,…,vn} V=v1,v2,…,vn [1] 。 G G G的邻接矩阵是一个具有下列性质的 n n n阶方阵:
①对无向图而言,邻接矩阵一定是对称的,而且主对角线一定为零(在此仅讨论无向简单图),副对角线不一定为 0 0 0,有向图则不一定如此。
②在无向图中,任一顶点i的度为第 i i i列(或第 i i i行)所有非零元素的个数,在有向图中顶点 i i i的出度为第i行所有非零元素的个数,而入度为第 i i i列所有非零元素的个数。
③用邻接矩阵法表示图共需要 n 2 n^2 n2个空间,由于无向图的邻接矩阵一定具有对称关系,所以扣除对角线为零外,仅需要存储上三角形或下三角形的数据即可,因此仅需要 n ( n − 1 ) / 2 n(n-1)/2 n(n−1)/2个空间。
咋一看,好像好深奥啊,我看不懂。
别急,举个如何把邻接矩阵画出来的例子就好理解了:
以这张图G1为例:
首先呢因为这是个无向无权图,所以它的邻接矩阵里面只有0和1,
让后呢把两个连通的的节点在邻接矩阵
V
V
V里设为
1
1
1,不能连通的设为
0
0
0
如,节点1和节点2能联通,所以把
V
(
1
,
2
)
V(1,2)
V(1,2)设为1
这样一顿操作后原本这样的邻接矩阵
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
1 | |||||||
2 | |||||||
3 | |||||||
4 | |||||||
5 | |||||||
6 | |||||||
7 |
变成了这样的
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
2 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
3 | 1 | 0 | 0 | 0 | 0 | 1 | 1 |
4 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
6 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
7 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
现在,你应该理解透彻了邻接矩阵的制作方法了,吧
接下来来实战演练一下:
示例讲解
首先来看看题面题目传送门:
1083: 自制-对立游戏邻接矩阵
题目描述
鸡哥(又名“sin雪梨鸡”)带领一群同学在玩对立游戏,简单来说就是每个人都要找寻自己对立的对象,找完后每个人要在5秒内记住场上的局势,5秒后谁能最完整地复述出来谁就赢了,最后一名要经历胜者惨无人道的惩罚(指午饭被拿走一些菜)鸡哥虽是这场游戏的领导者,但是他自己也不敢保证自己必赢,这时小陈老师走了出来,对他说:“我可以帮你观察局势,但我不知道如何表示我观察到的,如果你有可以表示的方法,我会帮你观察表示并投影在天花板上,到时候你直接看就行了,别人只会认为这是普通的投影”
鸡哥顿感心动,突然想到了前几天学过的邻接矩阵,鸡哥让老师用邻接矩阵来把局势投影到天花板上。小陈老师心想:“嘶,邻接矩阵我也没掌握熟练啊”,于是他准备让你帮帮他,你的程序必须在0.3秒内运行完,因为小陈老师摆投影要0.7秒,又因为小陈老师的电脑内存很小,所以你的程序必须在7MiB内运行完成输入
第1行: 一个整数N和一个整数M, 表示N个同学和M个对立行为 第2~M+1行: 输入两个整数i和j 表示i同学正在对立j同学
输出
N*N的邻接矩阵,其中两点间没联系的用0表示,有对立关系的点用1表示,点相重叠用2表示
样例输入
4 4
1 2
2 4
3 1
3 4样例输出
2 1 0 0
0 2 0 1
1 0 2 1
0 0 0 2提示
每个同学的编号依次为1~N
对于57%的数据:N,M<=50 对于29%的数据:N,M<=500 对于14%的数据:N<=10³,M<=10⁵
(后话:作者测试节点用了两个小时才搞完,来做一下吧QAQ)
首先先导入定义一堆东西:
#include<bits/stdc++.h>
using namespace std;
int a[1010][1010];//定义输出数组
int f,t;//定义输入的from和to
然后写主函数:
int main(){
int n,m; cin>>n>>m;//输入次数
for(int i=1;i<=m;i++){
cin>>f>>t;//输入这条边的from和to
a[f][t]=1;//将这条边在邻接矩阵中设为1
}
for(int i=1;i<=n;i++){
a[i][i]=2;//把对角线的设为2,因为对角线的一定是重叠的
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<a[f][t]<<" ";//输出
}
cout<<endl;//输出换行
}
}