次短路與k短路
阿新 • • 發佈:2018-12-14
次短路與第K短路
次短路是除了最短路之外第二短的路,這條路的長度有可能和最短路一樣長。 第K短路就是第K短的路,鑑於這兩個演算法都是特別模板的題,直接上例子
求次短路:Dijkstra的dist陣列和vis陣列再加一維,鬆弛的時候討論當前的路小於最短路,或者大於最短路但小於次短路這兩種情況,就能維護一個次短路了
#include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> using namespace std; const int maxn = 1000 + 5; const int INF = 0x3f3f3f3f; struct Node { int v, c, flag; Node (int _v = 0, int _c = 0, int _flag = 0) : v(_v), c(_c), flag(_flag) {} bool operator < (const Node &rhs) const { return c > rhs.c; } }; struct Edge { int v, cost; Edge (int _v = 0, int _cost = 0) : v(_v), cost(_cost) {} }; vector<Edge>E[maxn]; bool vis[maxn][2]; int dist[maxn][2]; void Dijkstra(int n, int s) { memset(vis, false, sizeof(vis)); for (int i = 1; i <= n; i++) { dist[i][0] = INF; dist[i][1] = INF; } priority_queue<Node>que; dist[s][0] = 0; que.push(Node(s, 0, 0)); while (!que.empty()) { Node tep = que.top(); que.pop(); int u = tep.v; int flag = tep.flag; if (vis[u][flag]) continue; vis[u][flag] = true; for (int i = 0; i < (int)E[u].size(); i++) { int v = E[u][i].v; int cost = E[u][i].cost; if (!vis[v][0] && dist[v][0] > dist[u][flag] + cost) { dist[v][1] = dist[v][0]; dist[v][0] = dist[u][flag] + cost; que.push(Node(v, dist[v][0], 0)); que.push(Node(v, dist[v][1], 1)); } else if (!vis[v][1] && dist[v][1] > dist[u][flag] + cost) { dist[v][1] = dist[u][flag] + cost; que.push(Node(v, dist[v][1], 1)); } } } } void addedge(int u, int v, int w) { E[u].push_back(Edge(v, w)); } int main() { //freopen("in.txt", "r", stdin); int n, m, v, w; while (scanf("%d", &n) != EOF) { for (int i = 0; i <= n; i++) E[i].clear(); for (int u = 1; u <= n; u++) { scanf("%d", &m); for (int j = 0; j < m; j++) { scanf("%d%d", &v, &w); addedge(u, v, w); } } Dijkstra(n, 1); printf("%d\n", dist[n][1]); } return 0; }
求S點到T點的第K短路的長度
#include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> using namespace std; const int maxn = 1000 + 5; const int INF = 0x3f3f3f3f; int s, t, k; bool vis[maxn]; int dist[maxn]; struct Node { int v, c; Node (int _v = 0, int _c = 0) : v(_v), c(_c) {} bool operator < (const Node &rhs) const { return c + dist[v] > rhs.c + dist[rhs.v]; } }; struct Edge { int v, cost; Edge (int _v = 0, int _cost = 0) : v(_v), cost(_cost) {} }; vector<Edge>E[maxn], revE[maxn]; void Dijkstra(int n, int s) { memset(vis, false, sizeof(vis)); for (int i = 1; i <= n; i++) dist[i] = INF; priority_queue<Node>que; dist[s] = 0; que.push(Node(s, 0)); while (!que.empty()) { Node tep = que.top(); que.pop(); int u = tep.v; if (vis[u]) continue; vis[u] = true; for (int i = 0; i < (int)E[u].size(); i++) { int v = E[u][i].v; int cost = E[u][i].cost; if (!vis[v] && dist[v] > dist[u] + cost) { dist[v] = dist[u] + cost; que.push(Node(v, dist[v])); } } } } int astar(int s) { priority_queue<Node> que; que.push(Node(s, 0)); k--; while (!que.empty()) { Node pre = que.top(); que.pop(); int u = pre.v; if (u == t) { if (k) k--; else return pre.c; } for (int i = 0; i < (int)revE[u].size(); i++) { int v = revE[u][i].v; int c = revE[u][i].cost; que.push(Node(v, pre.c + c)); } } return -1; } void addedge(int u, int v, int w) { revE[u].push_back(Edge(v, w)); E[v].push_back(Edge(u, w)); } int main() { //freopen("in.txt", "r", stdin); int n, m, u, v, w; while (scanf("%d%d", &n, &m) != EOF) { for (int i = 0; i <= n; i++) { E[i].clear(); revE[i].clear(); } for (int i = 0; i < m; i++) { scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); } scanf("%d%d%d", &s, &t, &k); Dijkstra(n, t); if (dist[s] == INF) { puts("-1"); continue; } if (s == t) k++; printf("%d\n", astar(s)); } return 0; }
轉自: