1,邻接矩阵(最好懂,最简单,最容易挂)
即通过开数组来表示点与点及其边的关系,如arr[i][j]可以表示i点与j点之间的边权为arr[i][j]这个数值
2,邻接表
思想:通过开一个动态数组来储存点与点及其边的关系,充分利用空间
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 100;
struct note
{
int s, p;
};
bool vis[N];//用于标记是否访问过这个点
vector<note>arr[N];
int main()
{
int n, m;
cin >> n >> m;
int u, v, w;
for (int i = 1; i <= m; ++i)
{
cin >> u >> v >> w;
arr[u].push_back({v, w});//存入一条由u指向v,边权为w的边
//arr[v].push_back({u,w}); ———— //如果是无向边,再换个方向来一次
}
int tmp=2;//访问的时候可以访问由tmp出发的所有边,可以对其操作
for(int i=0;i<(int)arr[tmp].size();++i){
}
}
3,链式向前星(本质:用链表实现的邻接表)
跟邻接表差不多,但是比邻接表快,因为他是由静态数组组成,邻接表是动态数组。但是邻接表写起来比他好懂,也比他容易
先上代码
struct shu
{
ll next, to,w;
} edge[N];
void add(ll f, ll t,ll z)
{
edge[++num].next = head[f];
edge[num].to = t;
edge[num].w=z;
head[f] = num;
}
//经典遍历公式
for (int i = head[u]; i; i = edge[i].next)
1,符号的意义
1,edge[].to存储由f,出发到达的终点,edge[].z表示这条边的权值
2,edge[].next储存上一次以f为起点的边(所以他==head[f],俩者就是等价的,即edge[num].next==edge[head[f]].next,这样看是不是更明显表现出是以f出发的边,head[f]的f表示从f出发的点,head[f]储存上一次以f为起点的边
3,不需要管num,只是暂时储存边的,最后会被替换为
edge[现在的边].next==head[f](上一条以f为起点的边)
edge[i].to==edge[edge[].next].to==edge[上一条以f为起点的边].to==上一条以f为起点的边指向的终点
2,遍历公式:for (int i = head[u]; i; i = edge[i].next)
意思是首先进入以u为开头的最后一条边,如果这个边i不为0(即不存在)的话,下一次,进入以u开头的上一条边(如果存在的话)