图的概念:点和边组成的集合
边的方向:有向边:有向图;无向边:无向图;
边的权值:可以为负数和正数
点的度:度 = 出度 + 入度
图的存储:
1,佛洛依德算法-floyd:(邻间矩阵 => 二维数组)多元最短路径,占内存大,复杂度高
#include <iostream>
#include <cstring>
using namespace std;
int n, m, s, arr[1005][1005];
int main() {
memset(arr, 0x3F, sizeof(arr));
cin >> n >> m >> s;
for (int i = 1; i <= n; i++) {
arr[i][i] = 0;
}
for (int i = 0; i < m; i++) {
int s, e, v;
cin >> s >> e >> v;
arr[s][e] = min(arr[s][e], v);
arr[e][s] = min(arr[e][s], v);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 1; k <= n; k++) {
arr[j][k] = min(arr[j][k], arr[j][i] + arr[i][k]);
}
}
}
for (int i = 1; i <= n; i++) {
if (arr[s][i] != 0x3F3F3F3F) cout << arr[s][i] << endl;
else cout << -1 << endl;
}
return 0;
}
2,邻间表:省空间,能快速知道以某点为起点的所有边的信息
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
int n, m;
int main() {
cin >> n >> m;
vector<vector<pair<int, int> > > edg(n + 1, vector<pair<int, int> >{});
for (int i = 0; i < m; i++) {
int s, e, v;
cin >> s >> e >> v;
edg[s].push_back(make_pair(e, v));
}
for (int i = 1; i <= n; i++) {
cout << i << ": ";
for (int j = 0; j < edg[i].size(); j++) {
cout << "{" << edg[i][j].first << ", " << edg[i][j].second << "} ";
}
cout << endl;
}
return 0;
}
3,链式前向星:省空间,快速
s e v
struct edgc {
int e, v, next;
}
edgc edg[10005];
int head[10005];
head[i]:以i为起点的最后一条边的编号
edg[j].next:和编号为j的边有相同起点的上一条边的编号
#include <iostream>
#include <cstring>
using namespace std;
struct edge {
int e, v, next;
};
edge edg[100005];
int n, m, head[100005];
int main() {
memset(head, -1, sizeof(head));
cin >> n >> m;
for (int i = 0; i < m; i++) {
int s, e, v;
cin >> s >> e >> v;
edg[i].e = e;
edg[i].v = v;
edg[i].next = head[s];
head[s] = i;
}
for (int i = 1; i <= n; i++) {
cout << i << " : ";
for (int j = head[i]; j != -1; j = edg[j].next) {
cout << "{" << edg[j].e << ", " << edg[j].v << "} ";
}
cout << endl;
}
return 0;
}
最短路径:
1,佛洛依德算法-floyd:(如上)
2,迪杰斯科拉算法-dijkstra(荷兰人):单元最短路径算法,只能有一个起点,且图中无负权边
采用“链式前向星”和“小顶堆”结合实现:
#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
struct node {
int now, val;
bool operator< (const node &b) const {
return this->val > b.val;
}
};
struct edge {
int e, v, next;
};
edge edg[200005];
int n, m, s, edg_cnt, head[100005], ans[100005];
void add_edg(int t1, int t2, int t3) {
edg[edg_cnt].e = t2;
edg[edg_cnt].v = t3;
edg[edg_cnt].next = head[t1];
head[t1] = edg_cnt;
edg_cnt++;
}
int main() {
memset(head, -1, sizeof(head));
memset(ans, 0x3f, sizeof(ans));
scanf("%d%d%d", &n, &m, &s);
for (int i = 0; i < m; i++) {
int t1, t2, t3;
scanf("%d%d%d", &t1, &t2, &t3);
add_edg(t1, t2, t3);
add_edg(t2, t1, t3);
}
priority_queue<node> que;
que.push((node){s, 0});
ans[s] = 0;
while (!que.empty()) {
node temp = que.top();
que.pop();
if (temp.val != ans[temp.now]) continue;
for (int i = head[temp.now]; i != -1; i = edg[i].next) {
int e = edg[i].e, v = edg[i].v;
if (ans[e] > temp.val + v) {
ans[e] = temp.val + v;
que.push((node){e, ans[e]});
}
}
}
for (int i = 1; i <= n; i++) {
if (ans[i] != 0x3f3f3f3f) printf("%d\n", ans[i]);
else printf("-1\n");
}
return 0;
}