圖演算法(1)
阿新 • • 發佈:2020-07-21
所有節點是從1到N號,並使用鄰接矩陣儲存
拓撲排序
int inDegree[MAXV]; bool topSort() { queue<int> q; int cnt = 0; for (int i = 1; i <= N; ++i) { if (!inDegree[i]) q.push(i); } while (!q.empty()) { int u = q.front(); q.pop(); for (int v = 1; v <= N; ++v) { if (Graph[u][v] != INF) { --inDegree[v]; if (!inDegree[v]) q.push(v); } } ++cnt; } if (cnt != N) return false; return true; }
最短路徑
Floyd
int dis[MAXV][MAXV]; void Floyd() { for (int k = 1; k <= N; ++k) { for (int u = 1; u <= N; ++u) { for (int v = 1; v <= N; ++v) { if (dis[u][k] != INF && dis[k][v] != INF && dis[u][k] + dis[k][v] < dis[u][v]) dis[u][v] = dis[u][k] + dis[k][v]; } } } }
dijkstra
使用幾種不同的優先順序尋找單源最短路徑,使用dijkstra + DFS
最方便
vector<int> pre[MAXV]; int Graph[MAXV][MAXV], N, d[MAXV]; bool vis[MAXV]; int s; void dijkstra() { using pr = pair<int, int>; // 堆優化尋找最小值 priority_queue<pr, vector<pr>, greater<pr> > heap; fill(d, d + MAXV, INF); fill(vis, vis + MAXV, false); heap.emplace(0, s); for (int i = 1; i <= N; ++i) heap.emplace(INF, i); for (int i = 0; i < N; ++i) { while (vis[heap.top().second]) heap.pop(); int u = heap.top().second; d[u] = heap.top().first; vis[u] = true; heap.pop(); for (int v = 1; v <= N; ++v) { if (!vis[v] && Graph[u][v] != INF) { if (d[u] + Graph[u][v] < d[v]) { d[v] = d[u] + Graph[u][v]; heap.emplace(d[v], v); pre[v].clear(); pre[v].push_back(u); } else if (d[u] + Graph[u][v] == d[v]) { pre[v].push_back(u); } } } } } int opt; vector<int> path, tmpPath; void DFS(int v) { tmpPath.push_back(v); if (v == s) { int tmpOpt; // 計算 tmpOpt if (tmpOpt < opt) { opt = tmpOpt; path = tmpPath; } } else for (auto &i : pre[v]) DFS(i); tmpPath.pop_back(); }
SPFA
之後補
最小生成樹
稠密圖用prim
,稀疏圖用dijkstra
prim
// 和dijkstra寫法類似,只是d[u]的含義表示到生成樹集合的距離
void prim() {
int ans = 0;
using pr = pair<int, int>;
priority_queue<pr, vector<pr>, greater<pr> > heap;
fill(d, d + MAXV, INF);
fill(vis, vis + MAXV, false);
heap.emplace(0, s);
for (int i = 1; i <= N; ++i) heap.emplace(INF, i);
for (int i = 0; i < N; ++i) {
while (vis[heap.top().second]) heap.pop();
int u = heap.top().second;
d[u] = heap.top().first;
ans += d[u];
vis[u] = true;
heap.pop();
for (int v = 1; v <= N; ++v) {
if (!vis[v] && Graph[u][v] != INF && Graph[u][v] < d[v]) {
d[v] = Graph[u][v];
heap.emplace(d[v], v);
}
}
}
}
kruskal
const int MAXE = 1000;
int father[MAXV];
struct edge {
int u, v, weight;
};
edge e[MAXE];
int findFather(int u) {
if (father[u] == u)
return u;
else {
int f = findFather(father[u]);
father[u] = f;
return f;
}
}
int kruskal() {
father[0] = 0;
iota(father + 1, father + MAXV, 1);
int ans = 0, cntEdge = 0;
for (int i = 0; i < N; ++i) {
int a = findFather(e[i].u), b = findFather(e[i].v);
if (a != b) {
father[a] = b;
ans += e[i].weight;
++cntEdge;
}
if (cntEdge == N - 1) break;
}
if (cntEdge != n - 1) return -1;
return ans;
}
關鍵路徑
之後再補