题目链接:https://nanti.jisuanke.com/t/31445
思路:
第k短路的模板题;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
#include<string>
#include<set>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0);
#define REP(i,n) for(int i=0;i<n;++i)
int read(){
int r=0,f=1;char p=getchar();
while(p>'9'||p<'0'){if(p=='-')f=-1;p=getchar();}
while(p>='0'&&p<='9'){r=r*10+p-48;p=getchar();}return r*f;
}
typedef long long ll;
typedef unsigned long long ull;
const int Maxn = 1010;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;
const int Mod = 1e6+7;
const double PI = acos(-1.0);
struct Edge {
int to,w,next;
} edges[10010],edges1[10010];
int head[Maxn],head1[Maxn],dis[Maxn],cnt[Maxn]; // head1 反向,head正向
bool used[Maxn];
void spfa(int s,int V) { // spfa找e到其他点的最短路
queue<int> qu;
for (int i = 1; i <= V; ++i) dis[i] = INF;
memset(used,0,sizeof(used));
dis[s] = 0;
used[s] = true;
qu.push(s);
int u,v,w;
while (!qu.empty()) {
u = qu.front(); qu.pop();
used[u] = false;
for (int i = head1[u]; i != -1; i = edges1[i].next) {
v = edges1[i].to; w = edges1[i].w;
if(dis[u] != INF && dis[v] > dis[u]+w) {
dis[v] = dis[u]+w;
if(!used[v]) {
used[v] = true;
qu.push(v);
}
}
}
}
}
struct F {
int f,g,u; // g为当前点到s的距离,f = g+dis[(当前点)](因为dis是e到其他点的最短路,所以是一个准确的"估计值")
F(int x,int y,int z):f(x),g(y),u(z) {}
bool operator < (const F &a1) const { // 注意优先队列的大小于号
if(f == a1.f) return g > a1.g;
else return f > a1.f;
}
};
bool Astar (int V,int s,int e,int k,int T) {
priority_queue<F> qu;
for (int i = 1; i <= V; ++i) cnt[i] = 0; // 记录点走过的次数,一个点可能走多次
if(dis[s] == INF) return false;
qu.push(F(dis[s],0,s));
while (!qu.empty()) {
F tp = qu.top(); qu.pop();
int u = tp.u;
cnt[u]++;
if(cnt[u] <= k && tp.g > T) return false; // 如果当前点小于或者等于k并且权值已经大于T了,说明k短路一定大于T
if(cnt[e] == k && tp.g <= T) return true;
if(cnt[u] > k) continue; // 当前点经过的次数大于k就不用考虑这个点
for (int i = head[u]; i != -1; i = edges[i].next) {
int v = edges[i].to, w = edges[i].w;
qu.push(F(dis[v]+tp.g+w,tp.g+w,v)); // f = dis[v]+当前点到s的距离+当前点到v的距离;
} // g = 当前点到s的距离+当前点到v的距离
}
return false;
}
int main (void)
{
int N,M,s,e,k,T;
while (scanf("%d%d",&N,&M) != EOF) {
scanf("%d%d%d%d",&s,&e,&k,&T);
int u,v,w;
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
for (int i = 0; i < M; ++i) { // 向前星存储正反方向的图(类似邻接表)
scanf("%d%d%d",&u,&v,&w);
edges[i].to = v;
edges[i].w = w;
edges[i].next = head[u];
head[u] = i;
edges1[i].to = u;
edges1[i].w = w;
edges1[i].next = head1[v];
head1[v] = i;
}
spfa(e,N); // 找出反向,e到其他点的单元最短路
if(Astar(N,s,e,k,T)) printf("yareyaredawa\n");
else printf("Whitesnake!\n");
}
return 0;
}

本文介绍了一种求解第K短路径问题的算法实现,通过SPFA算法预处理最短路径,结合A*搜索算法高效寻找从起点到终点的第K条最短路径。适用于图论与算法学习。

被折叠的 条评论
为什么被折叠?



