题意:给定一个图,求起点到终点的第k短路。
分析:先用dijkstra从t反向寻找最短路。然后使用A*算法,把f(i)=g(i) + h(i)。h(i)就是i点到t的最短距离。当某点出队次数达到k次的时候,结果为该点的当前路程+该点到t的最短距离。(我没有判断不连通的情况)
为什么这样做是对的呢?我们这样来思考,如果不实用最短路,而只使用A*那么t第x次出队的结果即为第x短路的距离。继而可以想到,从第一个出队次数达到x的点,沿着最短路走到t,一定是第x短路。
说实话我也没有完全理解。
另外注意s==t的情况,据说k要++,不明白为啥。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
usingnamespace std;
#define V 1005
#define E 1000005
int n, m, s, t, k;
#define typec int
// type of cost
const typec inf =0x3f3f3f3f;
// max of cost
typec cost[E], dist[V];
int e, pnt[E], nxt[E], head[V], prev[V], vis[V];
int pnt2[E], nxt2[E], head2[V], prev2[V], cost2[E];
struct pqnode
{
int v, dist;
pqnode(int vv =0, typec cc =0) :
v(vv), dist(cc)
{
}
};
struct qnode
{
int v;
typec c;
qnode(int vv =0, typec cc =0) :
v(vv), c(cc)
{
}
booloperator<(const qnode& r) const
{
return c > r.c;
}
};
booloperator<(const pqnode &a, const pqnode &b)
{
return a.dist + dist[a.v] > b.dist + dist[b.v];
}
void dijkstra(int n, constint src)
{
qnode mv;
int i, j, k, pre;
priority_queue<qnode> que;
vis[src] =1;
dist[src] =0;
que.push(qnode(src, 0));
for (pre = src, i =1; i < n; i++)
{
for (j = head[pre]; j !=-1; j = nxt[j])
{
k = pnt[j];
if (vis[k] ==0&& dist[pre] + cost[j] < dist[k])
{
dist[k] = dist[pre] + cost[j];
que.push(qnode(pnt[j], dist[k]));
prev[k] = pre;
}
}
while (!que.empty() && vis[que.top().v] ==1)
que.pop();
if (que.empty())
break;
mv = que.top();
que.pop();
vis[pre = mv.v] =1;
}
}
inline void addedge(int u, int v, typec c)
{
pnt[e] = v;
cost[e] = c;
nxt[e] = head[u];
head[u] = e++;
}
inline void addedge2(int u, int v, typec c)
{
pnt2[e] = v;
cost2[e] = c;
nxt2[e] = head2[u];
head2[u] = e++;
}
void input()
{
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
memset(prev, -1, sizeof(prev));
memset(head2, -1, sizeof(head2));
memset(prev2, -1, sizeof(prev2));
scanf("%d%d", &n, &m);
for (int i =0; i < n; i++)
dist[i] = inf;
for (int i =0; i < m; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
a--;
b--;
addedge2(a, b, c);
addedge(b, a, c);
}
scanf("%d%d%d", &s, &t, &k);
s--;
t--;
if (s == t)
k++;
}
int astar()
{
memset(vis, 0, sizeof(vis));
priority_queue<pqnode> pq;
pq.push(pqnode(s, 0));
while (!pq.empty())
{
pqnode pre = pq.top();
pq.pop();
vis[pre.v]++;
if (vis[pre.v] == k)
return pre.dist + dist[pre.v];
for (int i = head2[pre.v]; i !=-1; i = nxt2[i])
if (vis[pnt2[i]] <= k)
pq.push(pqnode(pnt2[i], pre.dist + cost2[i]));
}
return-1;
}
int main()
{
// freopen("t.txt", "r", stdin);
input();
dijkstra(n, t);
printf("%d\n", astar());
return0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
usingnamespace std;
#define V 1005
#define E 1000005
int n, m, s, t, k;
#define typec int
// type of cost
const typec inf =0x3f3f3f3f;
// max of cost
typec cost[E], dist[V];
int e, pnt[E], nxt[E], head[V], prev[V], vis[V];
int pnt2[E], nxt2[E], head2[V], prev2[V], cost2[E];
struct pqnode
{
int v, dist;
pqnode(int vv =0, typec cc =0) :
v(vv), dist(cc)
{
}
};
struct qnode
{
int v;
typec c;
qnode(int vv =0, typec cc =0) :
v(vv), c(cc)
{
}
booloperator<(const qnode& r) const
{
return c > r.c;
}
};
booloperator<(const pqnode &a, const pqnode &b)
{
return a.dist + dist[a.v] > b.dist + dist[b.v];
}
void dijkstra(int n, constint src)
{
qnode mv;
int i, j, k, pre;
priority_queue<qnode> que;
vis[src] =1;
dist[src] =0;
que.push(qnode(src, 0));
for (pre = src, i =1; i < n; i++)
{
for (j = head[pre]; j !=-1; j = nxt[j])
{
k = pnt[j];
if (vis[k] ==0&& dist[pre] + cost[j] < dist[k])
{
dist[k] = dist[pre] + cost[j];
que.push(qnode(pnt[j], dist[k]));
prev[k] = pre;
}
}
while (!que.empty() && vis[que.top().v] ==1)
que.pop();
if (que.empty())
break;
mv = que.top();
que.pop();
vis[pre = mv.v] =1;
}
}
inline void addedge(int u, int v, typec c)
{
pnt[e] = v;
cost[e] = c;
nxt[e] = head[u];
head[u] = e++;
}
inline void addedge2(int u, int v, typec c)
{
pnt2[e] = v;
cost2[e] = c;
nxt2[e] = head2[u];
head2[u] = e++;
}
void input()
{
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
memset(prev, -1, sizeof(prev));
memset(head2, -1, sizeof(head2));
memset(prev2, -1, sizeof(prev2));
scanf("%d%d", &n, &m);
for (int i =0; i < n; i++)
dist[i] = inf;
for (int i =0; i < m; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
a--;
b--;
addedge2(a, b, c);
addedge(b, a, c);
}
scanf("%d%d%d", &s, &t, &k);
s--;
t--;
if (s == t)
k++;
}
int astar()
{
memset(vis, 0, sizeof(vis));
priority_queue<pqnode> pq;
pq.push(pqnode(s, 0));
while (!pq.empty())
{
pqnode pre = pq.top();
pq.pop();
vis[pre.v]++;
if (vis[pre.v] == k)
return pre.dist + dist[pre.v];
for (int i = head2[pre.v]; i !=-1; i = nxt2[i])
if (vis[pnt2[i]] <= k)
pq.push(pqnode(pnt2[i], pre.dist + cost2[i]));
}
return-1;
}
int main()
{
// freopen("t.txt", "r", stdin);
input();
dijkstra(n, t);
printf("%d\n", astar());
return0;
}