存图方式

若不另加说明,以u,vu,v 表示两个点,ww 表示边权,nn 表示点数,mm 表示边数。

直接存边

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Edge {
int u, v, w;
};
vector<Edge> E;

void add(int u, int v, int w) { E.push_back({ u, v, w }); }
bool findedge(int u0, int v0) {
for (auto [u,v,w] : E) if (u == u0 && v == v0) return 1;
return 0;
}
void dfs(int u) {
if (vis[u]) return;
vis[u] = 1;
for (auto e : E) if (e.u == u) dfs(e.v);
}

查询边Θ(m)\Theta(m),遍历某点的出边Θ(m)\Theta(m),遍历图Θ(nm)\Theta(nm),空间Θ(m)\Theta(m)

邻接矩阵

1
2
3
4
5
6
7
8
bool E[N][N]; // Adjacency Matrix
void add(int u, int v, int w) { E[u][v] = w; }
bool findedge(int u, int v) { return E[u][v]; }
void dfs(int u) {
if (vis[u]) return;
vis[u] = 1;
for (int v = 1; v <= n; ++v) if (E[u][v]) dfs(v);
}

查询边Θ(1)\Theta(1),遍历某点的出边Θ(n)\Theta(n),遍历图Θ(n2)\Theta(n^2),空间Θ(n2)\Theta(n^2)

  • 查询操作是Θ(1)\Theta(1) 的;
  • 不适用于重边不可忽略的情况;
  • 空间较大;
  • 在稀疏图上效率低。

邻接表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Edge {
int v, w;
};
vector<Edge> E[N];

void add(int u, int v, int w) { E[u].push_back({ v, w }); }
bool findedge(int u0, int v0) {
for (auto [v,w] : E[u0]) if (v == v0) return 1;
return 0;
}

void dfs(int u) {
if (vis[u]) return;
vis[u] = 1;
for (auto e : E[u]) dfs(e.v);
}

查询边Θ(log(d+(u)))\Theta(\log(d^+(u))),遍历某点的出边Θ(d+(u))\Theta(d^+(u)),遍历图Θ(n+m)\Theta(n+m),空间Θ(m)\Theta(m)

  • 尤其适用于对某点的出边排序。

链式前向星

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Chain Forward Star
struct Edge {
int nxt, to, w;
};
vector<Edge> E;
int head[N];
inline void add(int u, int v, int w) {
E.push_back({ head[u], v, w });
head[u] = E.size() - 1;
}
bool findedge(int u, int v) {
for (int i = head[u]; i >= 1; i = E[i].nxt) if (E[i].to == v) return 1;
return 0;
}
void dfs(int u) {
if (vis[u]) return;
vis[u] = true;
for (int i = head[u]; i >= 1; i = E[i].nxt) dfs(E[i].to);
}
void eachT() {
E.push_back({ -1,0,0 });
for(;;) { add(u, v, w) };
}

查询边Θ(d+(u))\Theta(d^+(u)),遍历某点的出边Θ(d+(u))\Theta(d^+(u)),遍历图Θ(n+m)\Theta(n+m),空间Θ(m)\Theta(m)

  • 边是带编号的;
  • 不能对某点的出边排序。