题目
分析
裸的次短路,直接套k短路模板就行了。有兴趣的读者可以看我讲k短路的博客,是利用 spfa 和 A∗ 算法实现的。链接:POJ 2449 A* + spfa求第k短路 。
代码
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long int LL;
const int INF = 0x3f3f3f3f;
const int N = 100005;
struct state
{
LL u, g, h;
bool operator < (const state &x) const
{
return g + h > x.g + x.h;
}
};
struct edge{int to, cost;};
vector<edge> G1[N]; // 原图
vector<edge> G2[N]; // 反向图
int s, t, k; // s 起点,t 终点,k 第k短路。
int n, m; // n个点,m条边
LL d[N];
void spfa(int s)
{
int In_que[N] = {0};
memset(d, INF, sizeof(d));
queue<int> Q;
Q.push(s);
d[s] = 0;
In_que[s] = 1;
while (!Q.empty())
{
int u = Q.front();
Q.pop();
In_que[u] = 0;
for (unsigned i = 0; i < G2[u].size(); i++)
{
edge e = G2[u][i];
int v = e.to, dd = d[u] + e.cost;
if (d[v] > dd)
{
d[v] = dd;
if (!In_que[v])
{
Q.push(v);
In_que[v] = 1;
}
}
}
}
}
void Astar()
{
int cnt[N] = {0};
priority_queue<state> Q;
Q.push({s, 0, d[s]});
while (!Q.empty())
{
state cur = Q.top();
Q.pop();
int u = cur.u;
cnt[u]++;
if (cnt[u] == k && u == t)
{
printf("%I64d\n", cur.g);
break;
}
if (cnt[u] > k)
continue;
for (unsigned i = 0; i < G1[u].size(); i++)
{
edge e = G1[u][i];
if (cnt[e.to] != k)
Q.push({e.to, cur.g + e.cost, d[e.to]});
}
}
}
void K_Path(int s_val, int t_val, int k_val)
{
s = s_val;
t = t_val;
k = k_val;
spfa(t);
Astar();
}
int main()
{
//freopen("test.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T;
scanf("%d", &T);
while (T--)
{
for (int i = 0; i < N; i++)
{
G1[i].clear();
G2[i].clear();
}
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++)
{
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
G1[u].push_back({v, c});
G1[v].push_back({u, c});
G2[v].push_back({u, c});
G2[u].push_back({v, c});
}
K_Path(1, n, 2);
}
return 0;
}