BZOJ 1975 魔法猪学院(A*求K短路)
显然每次贪心的走最少消耗的路径即可。那么也就是找出最短路,次短路,,,K短路之后消耗E的能量的最多的路径条数。
也就是裸的A*算法。
#include <bits/stdc++.h> using namespace std; typedef double lf; const int N=5005, M=200005; lf d[N], En; typedef pair<lf, int> pr; #define mkpr(x, y) make_pair<lf, int> (x, y) priority_queue<pr, vector<pr>, greater<pr> >q; struct Gr { struct E { int next, to; lf w; }e[M]; int n, ihead[N], cnt; void add(int x, int y, lf w) { e[++cnt]=(E){ihead[x], y, w}; ihead[x]=cnt; } void dij() { static bool vis[N]; memset(vis, 0, sizeof(bool)*(n+1)); for(int i=1; i<=n; ++i) { d[i]=1e150; } d[n]=0; q.push(mkpr((lf)0, n)); while(q.size()) { int x=q.top().second; q.pop(); if(vis[x]) { continue; } vis[x]=1; for(int i=ihead[x]; i; i=e[i].next) { int y=e[i].to; if(d[y]>d[x]+e[i].w) { d[y]=d[x]+e[i].w; q.push(mkpr(d[y], y)); } } } } int getans() { int ans=0; q.push(mkpr(d[1], 1)); while(En>0 && q.size()) { int x=q.top().second; lf g=q.top().first-d[x]; q.pop(); if(x==n) { if(En>=g) { En-=g; ++ans; continue; } else { break; } } for(int i=ihead[x]; i; i=e[i].next) { int y=e[i].to; lf w=e[i].w; // 有精度误差啊,不能乱减枝啊 q.push(mkpr(g+w+d[y], y)); } } return ans; } }g, G; int main() { int n, m; scanf("%d%d%lf", &n, &m, &En); g.n=G.n=n; for(int i=1; i<=m; ++i) { int x, y; lf e; scanf("%d%d%lf", &x, &y, &e); g.add(x, y, e); G.add(y, x, e); } G.dij(); printf("%d\n", g.getans()); return 0; }