001.图的存储
转载出处董晓老师
1.邻接矩阵
二维数组\(w[u][v]\)存储点\(u\)到点\(v\)的边权
时间复杂度:\(O(n^2)\)
空间复杂度:\(O(n^2)\)
应用:稠密图以外基本不用
(1)加边操作
void add(int a, int b, int c)
{
w[a][b] = c;
}
(2)遍历操作
void dfs(int u)
{
···
vis[u] = true;
for (int v = 1; v <= n; v++)
{
if (w[u][v])
{
...
if (vis[v]) continue;
dfs(v);
...
}
}
...
}
2.边集数组
边集数组\(e[i]\)存第\(i\)条边的\(\{起点u,终点v,边权w\}\)
时间复杂度:\(O(nm)\)
空间复杂度:\(O(m)\)
应用:Kruskal算法
(1)加边操作
struct edge
{
int u, v, w;
}e[M];
void add(int i, int a, int b, int c)
{
e[i] = { a,b,c };
}
(2)遍历操作
void dfs(int u)
{
...
vis[u] = true;
for (int i = 1; i <= m; i++)
{
if (e[i].u == u)
{
int v = e[i].v, w = e[i].w;
...
if (vis[v]) continue;
dfs(v);
...
}
}
...
}
3.邻接表
出边数组\(e[u][i]\)存储u点的所有出边的\(\{终点v,边权w\}\)
时间复杂度:\(O(n+m)\)
空间复杂度:\(O(n+m)\)
应用:各种图,不能存反向边
(1)加边操作
struct edge
{
int v, w;
};
vector<edge> e[N];
void add(int a, int b, int c)
{
e[a].push_back({ b,c });
}
(2)遍历操作
void dfs(int u, int fa)
{
...
for (auto ed : e[u])
{
int v = ed.v, w = ed.w;
if (v == fa) continue;
...
dfs(v, u);
...
}
...
}
4.链式前向星
一个表头数组悬挂多个链表
边集数组\(e[i]\)存储第\(i\)条边的\(\{终点v,边权w,下一条边ne\}\)
表头数组\(h[u]\)存储\(u\)点的第一条出边的编号
边的编号\(idx=0,1,2,···\)
时间复杂度:\(O(n+m)\)
空间复杂度:\(O(n+m)\)
(1)加边操作
struct edge
{
int v, w, ne;
}e[M];
int idx, h[N];
void add(int a, int b, int c)
{
e[idx] = { b,c,h[a] };
h[a] = idx++;
}
(2)遍历操作
void dfs(int u, int fa)
{
...
for (int i = h[u]; ~i; i = e[i].ne)
{
int v = e[i].v, w = e[i].w;
if (v == fa) continue;
...
dfs(v, u);
...
}
...
}

浙公网安备 33010602011771号