高级图算法
高级图算法包括最小生成树、最短路径变种、差分约束和分层图技术,在竞赛编程中广泛应用。
最小生成树算法
最小生成树使用恰好n-1条边以最小总权重连接所有顶点。
Kruskal和Prim最小生成树算法
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
// 并查集用于Kruskal算法
class UnionFind {
private:
vector<int> parent, rank;
public:
UnionFind(int n) : parent(n), rank(n, 0) {
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
bool unite(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return false;
// 按秩合并
if (rank[px] < rank[py]) swap(px, py);
parent[py] = px;
if (rank[px] == rank[py]) rank[px]++;
return true;
}
};
// Kruskal算法
struct Edge {
int u, v, weight;
bool operator<(const Edge& other) const {
return weight < other.weight;
}
};
class KruskalMST {
private:
vector<Edge> edges;
int n;
public:
KruskalMST(int vertices) : n(vertices) {}
void addEdge(int u, int v, int w) {
edges.push_back({u, v, w});
}
pair<int, vector<Edge>> findMST() {
sort(edges.begin(), edges.end()); // 按权重排序
UnionFind uf(n);
vector<Edge> mst;
int totalWeight = 0;
for (const Edge& e : edges) {
if (uf.unite(e.u, e.v)) { // 不形成环
mst.push_back(e);
totalWeight += e.weight;
if (mst.size() == n - 1) break;
}
}
return {totalWeight, mst};
}
};
int main() {
cout << "Kruskal最小生成树算法测试:" << endl;
KruskalMST kruskal(4);
kruskal.addEdge(0, 1, 10);
kruskal.addEdge(0, 2, 6);
kruskal.addEdge(0, 3, 5);
kruskal.addEdge(1, 3, 15);
kruskal.addEdge(2, 3, 4);
auto [weight, mst] = kruskal.findMST();
cout << "MST总权重: " << weight << endl;
cout << "MST边:" << endl;
for (const Edge& e : mst) {
cout << e.u << " - " << e.v << " (权重: " << e.weight << ")" << endl;
}
return 0;
}Kruskal算法按权重对边排序,使用并查集检测环,逐步构建最小生成树。
高级最短路径算法
除了基本的Dijkstra和Floyd-Warshall,高级技术处理特殊约束和优化。
带路径重构的Dijkstra算法
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
class DijkstraWithPath {
private:
vector<vector<pair<int, int>>> graph;
int n;
public:
DijkstraWithPath(int vertices) : n(vertices), graph(vertices) {}
void addEdge(int u, int v, int w) {
graph[u].push_back({v, w});
}
pair<vector<int>, vector<int>> shortestPath(int start) {
vector<int> dist(n, INT_MAX);
vector<int> parent(n, -1);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
dist[start] = 0;
pq.push({0, start});
while (!pq.empty()) {
int d = pq.top().first;
int u = pq.top().second;
pq.pop();
if (d > dist[u]) continue;
for (auto& edge : graph[u]) {
int v = edge.first;
int w = edge.second;
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
parent[v] = u;
pq.push({dist[v], v});
}
}
}
return {dist, parent};
}
vector<int> reconstructPath(const vector<int>& parent, int start, int end) {
vector<int> path;
int curr = end;
while (curr != -1) {
path.push_back(curr);
curr = parent[curr];
}
reverse(path.begin(), path.end());
// 检查路径是否存在
if (path[0] != start) {
return {};
}
return path;
}
};
int main() {
cout << "带路径重构的Dijkstra算法测试:" << endl;
DijkstraWithPath dijkstra(5);
dijkstra.addEdge(0, 1, 4);
dijkstra.addEdge(0, 2, 2);
dijkstra.addEdge(1, 2, 1);
dijkstra.addEdge(1, 3, 5);
dijkstra.addEdge(2, 3, 8);
dijkstra.addEdge(2, 4, 10);
dijkstra.addEdge(3, 4, 2);
auto [dist, parent] = dijkstra.shortestPath(0);
cout << "从顶点0的最短距离:" << endl;
for (int i = 0; i < dist.size(); i++) {
cout << "到 " << i << ": " << dist[i] << endl;
}
cout << "\n从0到4的路径:" << endl;
vector<int> path = dijkstra.reconstructPath(parent, 0, 4);
for (int i = 0; i < path.size(); i++) {
cout << path[i];
if (i < path.size() - 1) cout << " -> ";
}
cout << endl;
return 0;
}增强的Dijkstra算法不仅找到最短距离,还使用父指针重构实际路径。