图论-概念与记录图的方法
第一天
TOP1:概念
图论是什么?
图中有许多结点,结点之间有许多边。
举个例子:你在一个村庄里,村庄中有一些房子(你的邻居啦),而这些房子有许多小路连接(为了串门呗)。现在就有一堆关于这个村庄的问题。
那么有路径,路就会有长度和方向,在今后各位做题目时,题目就会有描述: 有向边、无向边 和 有权图、无权图 。
有向边、无向边 : 即这条边有没有单一方向。例如一条连接 \(x\) 和 \(y\) 的边,只能从 \(x\) 走向 \(y\),那么这条边就是有向边。无向边就是两地可互相通往。
有权图、无权图 :权值就是一条边的长度或经过所需代价,有时也可以指经过一个点所需代价。有权图好理解,无权图这里要注意: 不是边的权值为 \(0\),而是全都为 \(1\)
Top2:图的记录方法
大家应该对图有一定的概念了,那么,该怎么去记录图呢?
邻接矩阵
这是一个很实用的东东,在比赛时好写,好调用,是新手必备之物。
显然,矩阵肯定是矩形。描述矩形的两个要素是 长 与 宽 。所以,邻接矩阵是 二维数据 :dis[ ][ ]
对于 \(dis[x][y]\),指从 \(x\) 点 到 \(y\) 点所需要的代价或花费。易得:无权图整张图仅仅由 \(0\) , \(1\) 构成,此时 \(dis[x][y]\) 的定义可简化为两点之间是否有边连接。
对于一个有 \(4\) 个点 \((A、B、C、D)\) , \(3\) 条边的无权图:
\(A\) 连着 \(B\),\(B\) 连着 \(C\),\(C\) 连着 \(A\),\(D\) 单独点;
无向,无权,那么邻接矩阵会是这样:
A B C D
A 0 1 1 INF
B 1 0 1 INF
C 1 1 0 INF
D INF INF INF 0
显而易见:
-
无向图的邻接矩阵是对称的 , 而有向图不同。
-
一个点到自己的距离是0,到没有直接边连接的两个点之间的权值是无穷大。
所以:邻接矩阵要初始化
如下:
for(int i = 1; i <= n; i++)
{
for(int j = i + 1; j <= n; j++)
{
dis[i][j] = dis[j][i] = (i == j) ? 0 : INF;
}
}
在输入的时候,通常是 \(x\)、\(y\)、\(z\) (起始点,终止点,权值),操作如下
cin>>n>>m;//n表示点的数量,m表示边的数量
for(int i = 1;i <= m; i++){//枚举输入边
cin>>x>>y>>z;//如上描述
//有向边:
dis[x][y] = z;
//无向边:
dis[x][y] = dis[y][x] = z;
}
链式前向星
名字很高大上,其实......就是链表。
博主很弱,如果看不大懂下面链式前向星和动态数组记录方法的,就不要看了,掌握好邻接矩阵吧
首先是变量定义:
int cnt;//用于添边时的编号计数
int w[10000];//记录边的权值
int next[10000];//记录每一条边的最开头的边的编号
int to[10000];//记录每一条边的终点
int first[10000] = {0};//记录每个点的最开头的边的编号
添边操作:
void addEdge(int u, int v, int weight)
{
cnt++; //边的编号
to[cnt] = v; //第cnt条边指向点v
w[cnt] = weight; //第cnt条边的权值
next[cnt] = first[u]; // 第cnt条边指向连接点u的第一条边
first[u] = cnt; //将连接点u的第一条边更新为第cnt条边
return;
}
然后......就没有然后了说了博主很弱,不用这个,顺便提一下而已
分割线
分割线
动态数组
和邻接矩阵没啥区别,也是二维数组,不过......省空间而已
如果有动态数组不会用的......百度吧
定义:
vector<int>nei[MAXN];
简单粗暴的模板
其他初始化读入啥的,见邻接矩阵吧......
好了,第一天就到这里,是不是收获很多呢毒瘤?欢迎在下方留言!