图的存储有四样写法,你知道么?
直接存边
#include<iostream>
#define M 100005
using namespace std;
struct Edge {
int u; // 起点
int v; // 终点
int w; // 边权
} e[M];
int n, m;
int main() {
cin >> n; // 点数
cin >> m; // 边数
for(int i = 1; i <= m; ++i) {
cin >> e[i].u >> e[i].v >> e[i].w;
}
return 0;
}
邻接矩阵
使用一个二维数组 adj
来存边,其中 adj[u][v]
为
t
r
u
e
true
true 表示存在
u
u
u 到
v
v
v 的边,为
f
a
l
s
e
false
false 表示不存在。
#include<iostream>
#define N 1003
using namespace std;
bool adj[N][N]; // 邻接矩阵(无边权)
int n, m;
int u, v;
int main() {
cin >> n; // 点数
cin >> m; // 边数
for(int i = 1; i <= m; ++i) {
cin >> u >> v;
adj[u][v] = true;
/*
建双向边
adj[u][v] = true;
adj[v][u] = true;
*/
}
return 0;
}
如果是带边权的图,可以在 adj[u][v]
中存储
u
u
u 到
v
v
v 的边的边权。
#include<iostream>
#define N 1003
using namespace std;
int adj[N][N]; // 邻接矩阵(有边权)
int n, m;
int u, v, w;
int main() {
cin >> n; // 点数
cin >> m; // 边数
for(int i = 1; i <= m; ++i) {
cin >> u >> v >> w;
adj[u][v] = w;
/*
建双向边
adj[u][v] = w;
adj[v][u] = w;
*/
}
return 0;
}
邻接表
使用 vector<Node> adj[n]
来存边,其中 adj[u]
存储的是点
u
u
u 的所有出边的相关信息(终点、边权等)。
#include<iostream>
#include<vector>
#define N 1003
using namespace std;
vector<int> adj[N];
int n, m;
int u, v;
int main() {
cin >> n; // 点数
cin >> m; // 边数
for(int i = 1; i <= m; ++i) {
cin >> u >> v;
adj[u].push_back(v);
/*
建双向边
adj[u].push_back(v);
adj[v].push_back(u);
*/
}
return 0;
}
#include<iostream>
#include<vector>
#define N 1003
using namespace std;
struct Node {
int v, w;
};
vector<Node> adj[N];
int n, m;
int u, v, w;
int main() {
cin >> n; // 点数
cin >> m; // 边数
for(int i = 1; i <= m; ++i) {
cin >> u >> v >> w;
adj[u].push_back((Node){v,w});
/*
建双向边
adj[u].push_back((Node){v,w});
adj[v].push_back((Node){u,w});
*/
}
return 0;
}
链式前向星
本质是用链表实现的邻接表
to
和 w
分别表示边的终点和权值
next
表示与这个边起点相同的上一条边的编号
head[i]
表示以
i
i
i 为起点的最后一条边的编号
head
数组一般初始化为
−
1
-1
−1
#include<iostream>
#include<cstring>
#define M 100005
using namespace std;
struct Edge {
int to; // 边的终点
int w; // 边的权值
int next; // 与该边同起点的上一条边的存储位置
} edge[M];
int head[M], cnt; // head[i] 表示以 i 为起点的最后一条边的存储位置
int n, m;
int u, v, w;
void add_edge(int u, int v, int w) {
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
int main() {
memset(head,-1,sizeof(head));
cin >> n; // 点数
cin >> m; // 边数
for(int i = 1; i <= m; ++i) {
cin >> u >> v >> w;
add_edge(u,v,w); // 加边
/*
建双向边
add_edge(u,v,w);
add_edge(v,u,w);
*/
}
// 遍历所有边
for(int i = 1; i <= n; ++i) {
for(int j = head[i]; ~j; j = edge[j].next) { // ~j 表示 j != -1
cout << i << "->" << edge[j].to << " " << edge[j].w << endl;
}
}
return 0;
}
/*
4 6
1 2 2
1 3 3
1 4 4
2 3 6
2 4 8
3 4 12
*/