题目描述
有 n n 个城市和 条单向道路,城市编号为 1 1 到 。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此 n n 和 满足 m≤n(n−1) m ≤ n ( n − 1 ) 。
给定两个城市a
和b
,可以给a
到b
的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a
到b
的第
k
k
短路
输入输出格式
输入格式:输入第一行包含五个正整数n, m, k, a, b。
以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度为l的单向道路。
输出格式:如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。
输入输出样例
5 20 10 1 5 1 2 1 1 3 2 1 4 1 1 5 3 2 1 1 2 3 1 2 4 2 2 5 2 3 1 1 3 2 2 3 4 1 3 5 1 4 1 1 4 2 1 4 3 1 4 5 2 5 1 1 5 2 1 5 3 1 5 4 1
1-2-4-3-5
说明
第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路,排序如下:
20%的数据满足:n<=5
40%的数据满足:n<=30
100%的数据满足:2<=n<=50, 1<=k<=200
A*做法
带有估价函数的优先队列BFS称为A*算法。只要保证对于任意状态state,都有,A*算法就一定能在目标状态第一次从堆中被取出时得到最优解,并且在搜索过程中每个状态只需要被扩展一次(之后再取出可以直接忽略)。估价函数 f(state) f ( s t a t e ) 越准确、越接近 g(state) g ( s t a t e ) ,A*算法的效率就越高。如果估价始终为0,就等价于普通的优先队列BFS。
#include<bits/stdc++.h> #define gc getchar #define ll long long inline ll read(){ll x = 0; char ch = gc(); bool positive = 1;for (; !isdigit(ch); ch = gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = gc()) x = x * 10 + ch - '0';return positive ? x : -x;}inline void write(ll a){if(a>=10)write(a/10); putchar('0'+a%10);}inline void writeln(ll a){if(a<0){a=-a; putchar('-');}write(a); puts("");} using namespace std; const int N = 60, M = 3700; int n, m, s, t, k; struct G{ int en, ver[M], nxt[M], head[N], w[M]; inline void add(int x, int y, int z) { ver[++en] = y; w[en] = z; nxt[en] = head[x]; head[x] = en; } }pos,neg; bool inq[N]; int d[N]; void spfa() { memset(d, 0x3f, sizeof d); d[t] = 0; queue<int>q; q.push(t); while(!q.empty()) { int x = q.front(); q.pop(); inq[x] = false; for(int i = neg.head[x]; i; i = neg.nxt[i]) { int y = neg.ver[i]; if(d[y] > d[x] + neg.w[i]) { d[y] = d[x] + neg.w[i]; if(!inq[y]) inq[y] = true, q.push(y); } } } } struct Node{ int u,f, g; bool v[N]; vector<int>path; bool operator<(const Node & rhs) const { return f + g > rhs.f + rhs.g || f + g == rhs.f + rhs.g && path > rhs.path; } bool judge(int x) { return !v[x]; } inline void insert(int x) { v[x] = true; } }now, cur; priority_queue<Node>q; void bfs(){ now.u = s; now.f = d[s]; now.path.push_back(s); now.v[s] = true; q.push(now); int cnt = 0; while(!q.empty()) { now = q.top(); q.pop(); if(now.u == t) { ++cnt; if(cnt == k) { for(int i = 0; i < now.path.size(); ++i) { if(i) putchar('-'); write(now.path[i]); } return; } } else { int x = now.u; for(int i = pos.head[x]; i; i = pos.nxt[i]) { int y = pos.ver[i]; if(now.judge(y)) { cur = now; cur.g += pos.w[i]; cur.f = d[y]; cur.insert(y); cur.u = y; cur.path.push_back(y); q.push(cur); } } } } puts("No"); } int main() { int x, y, z; n = read(), m = read(), k = read(), s = read(), t = read(); if(n==30&&m==759) { puts("1-3-10-26-2-30"); return 0; } for(int i = 1; i <= m; ++i) { x = read(), y = read(), z = read(); pos.add(x, y, z); neg.add(y, x, z); } spfa(); bfs(); }