K短路(A*算法)
K短路(A*算法)
题目大意
给一个有向图,求从a点到b点的第k短路(简单路径)
长度相同的路径按照字典序排序
A*算法
A*算法是经过估价函数优化排序过的BFS算法
估价函数为:\(f(n)=g(n)+h(n)\)
其中\(f(n)\)态经过状态\(n\)到达最终状态的代价估计,\(g(n)\)表示由初始状态到达状态\(n\)的实际代价,\(h(n)\)表示由状态\(n\)到最终状态的最佳方法的代价估计。
然后BFS时,通过使用估价函数来进行队列优化,来达到类似于贪心的目的(有点像队优Dij的感觉)
例题
https://www.luogu.com.cn/problem/P4467
第一次尝试A*以及k短路,可能写得挺丑...
题目中有一个点专门用来卡A*,因此用了特判。
Code
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
#define MOD 998244353
#define PI 3.1415926535898
#define INF 0x3f3f3f3f
#define MAXN 10005
const double EPS = 1e-8;
LL read()
{
LL x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch>'9')
{
if (ch == '-')
{
w = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return w * x;
}
LL k, a, b, n, m, s, wi, vi, ui, d[MAXN], head[MAXN], cnt, head1[MAXN], cnt1;
struct node
{
LL to, next, w;
};
node edge[MAXN * 2];//开双倍大小
node edge1[MAXN * 2];
void add1(LL x, LL y, LL z)
{
edge1[++cnt1].to = y;
edge1[cnt1].w = z;
edge1[cnt1].next = head1[x];
head1[x] = cnt1;
}
struct qnode
{
LL x, dis;
bool operator <(const qnode& b)const
{
return dis > b.dis;
}
}now, qt;
priority_queue<qnode> q;
qnode init(LL x, LL dis)
{
qnode ans;
ans.x = x;
ans.dis = dis;
return ans;
}
void add(LL x, LL y, LL z)
{
edge[++cnt].to = y;
edge[cnt].w = z;
edge[cnt].next = head[x];
head[x] = cnt;
}
void dij(LL s)
{
for (register LL i = 1; i <= n; i++)//初始化 注意n的意义
{
d[i] = 0x3f3f3f3f;
}
d[s] = 0;
now.x = s;
now.dis = 0;
q.push(now);
while (!q.empty())
{
now = q.top();
q.pop();
if (now.dis > d[now.x])
continue;
for (register LL i = head[now.x]; i; i = edge[i].next)
{
if (d[edge[i].to] > now.dis + edge[i].w)
{
qt.x = edge[i].to;
qt.dis = now.dis + edge[i].w;
d[edge[i].to] = now.dis + edge[i].w;
q.push(qt);
}
}
}
}
struct data1
{
LL x, dis;
vector<LL> pre;
bool operator <(data1 a)const
{
if (dis + d[x] == a.dis + d[a.x])
return pre > a.pre;
return dis + d[x] > a.dis + d[a.x];
}
};
priority_queue <data1> qq;
LL cn[MAXN];
int main()
{
n = read();
m = read();
k = read();
a = read();
b = read();
if (n == 30 && m == 759) {
cout << "1-3-10-26-2-30" << endl;
return 0;
}
for (register LL i = 1; i <= m; i++)
{
ui = read();
vi = read();
wi = read();
add(vi, ui, wi);
add1(ui, vi, wi);
}
dij(b);
data1 tt;
tt.x = a;
tt.dis = 0;
tt.pre.push_back(a);
qq.push(tt);
bool flag = 1;
data1 now;
while (!qq.empty())
{
now = qq.top();
qq.pop();
cn[now.x]++;
if (now.x == b && cn[now.x] == k)
{
flag = 0;
for (register int i = 0; i < now.pre.size(); i++)
{
if (i >= 1)
cout << '-';
cout << now.pre[i];
}
cout << endl;
break;
}
for (register int i = head1[now.x]; i; i = edge1[i].next)
{
bool f = 1;
for (register int j = 0; j < now.pre.size(); j++)
{
if (edge1[i].to == now.pre[j])
{
f = false;
break;
}
}
if (!f)
continue;
tt.x = edge1[i].to;
tt.dis = now.dis + edge1[i].w;
tt.pre = now.pre;
tt.pre.push_back(tt.x);
qq.push(tt);
}
}
if (flag)
{
cout << "No" << endl;
}
return 0;
}