这道题拿来做启发式搜索的入门题… 但是网上很多题解都不是很友好…
反正我这种蒟蒻是看不懂就对了
题目大概是给你一个有向图 要你找到 K K 条路,满足条路的权值和不大于一个给你的值,最大化 K K ,一看就知道是个短路的模板题…只是这里要求出这个 K K , 我们每求出一条次短路就更新一下当前权值和就好了,关键点在怎么求短路上
首先我们可以预处理出每个点到终点的最短距离,这里建反图跑最短路就能实现
首先我们引入一个东西 叫做乐观估价函数 f(x) f ( x )
f(x)=h(x)+g(x) f ( x ) = h ( x ) + g ( x )
h(x) h ( x ) 为起点到当前点实际费用
g(x) g ( x ) 为当前点到终点费用的估计
在这道题中 h(x) h ( x ) 就是从起点到当前点的费用
g(x) g ( x ) 就是当前点到终点的最短路。
通过这个估价函数,我们发现估价函数小的一定会更优。
我们可以用一个小根堆来维护其中的路径
每次像 Dijkstra D i j k s t r a 一样拓展节点,然后就做完了,搜到 n n <script type="math/tex" id="MathJax-Element-969">n</script>号点的时候加入答案即可
Codes
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define x first
#define y second
typedef double db;
typedef pair<double, int> PDI;
template<class T>inline bool chkmin(T &_, T __) {return _ > __ ? _ = __, 1 : 0;}
const int N = 5000 + 10;
vector<PDI> G1[N], G2[N];
int n, m, ans;
db dis[N], E;
void Dijkstra() {
priority_queue<PDI, vector<PDI>, greater<PDI> > q;
for(int i = 1; i <= n; ++ i) dis[i] = 1e9;
q.push(mp(dis[n] = 0, n));
while(!q.empty()) {
PDI k = q.top(); q.pop();
if(k.x > dis[k.y]) continue;
for(auto v : G1[k.y])
if(chkmin(dis[v.y], k.x + v.x))
q.push(mp(dis[v.y], v.y));
}
}
void A_Star() {
priority_queue<PDI, vector<PDI>, greater<PDI> > q;
q.push(mp(dis[1], 1));
while(!q.empty()) {
PDI k = q.top(); q.pop();
if(k.x > E) return;
int u = k.y;
if(u == n) {
E -= k.x; ++ ans; continue;
}
for(auto v : G2[u])
q.push(mp(k.x - dis[u] + v.x + dis[v.y], v.y));
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("1975.in", "r", stdin);
freopen("1975.out", "w", stdout);
#endif
int x, y; db z;
scanf("%d%d%lf", &n, &m, &E);
for(int i = 1; i <= m; ++ i) {
scanf("%d%d%lf", &x, &y, &z);
G1[y].pb(mp(z, x));
G2[x].pb(mp(z, y));
}
Dijkstra();
A_Star();
printf("%d\n", ans);
return 0;
}