题目:http://poj.org/problem?id=2449
分析:第k短路板子题
贴个板子:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1e3+2;
const int INF=0xfffffff;
int f[maxn];///评估函数,为当前点到终点的最短路
bool vis[maxn];
struct Node
{
int x;
int w;
Node(int x=0,int w=0):x(x),w(w) {}
};
struct Node1
{
int x;
int g,f;///g为当前代价,f为评估函数+当前代价
Node1(int x=0,int g=0,int f=0):x(x),g(g),f(f) {}
bool operator<(const Node1& a)const///先按f从小到大排,再按g从小到大排
{
if(f==a.f)
return g>a.g;
return f>a.f;
}
};
vector<Node>edge1[maxn];///反向边
vector<Node>edge2[maxn];///正向边
void init(int n)
{
for(int i=1; i<=n; i++)
f[i]=INF;
}
bool spfa(int s)///求每个点到终点v的最短路,以此来确定评估函数
{
memset(vis,0,sizeof vis);
vis[s]=1;
f[s]=0;
queue<int>q;
q.push(s);
while(!q.empty())
{
int cur=q.front();
q.pop();
vis[cur]=0;
for(int i=0; i<edge1[cur].size(); i++)
{
int v=edge1[cur][i].x;
int w=edge1[cur][i].w;
if(f[v]>w+f[cur])
{
f[v]=w+f[cur];
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
int Astar(int s,int e,int k)
{
if(f[s]==INF) return -1;
if(s==e) ++k;///起点和终点相同时距离为0不能算最短路
priority_queue<Node1>q;
Node1 cur,nex;
cur.x=s;
cur.g=0;
cur.f=cur.g+f[cur.x];
q.push(cur);
int num=0;
while(!q.empty())
{
cur=q.top();
q.pop();
if(cur.x==e) ++num;
if(num==k) return cur.g;
for(int i=0; i<edge2[cur.x].size(); i++)
{
nex.x=edge2[cur.x][i].x;
nex.g=edge2[cur.x][i].w+cur.g;///下次代价=当前代价+这条边长
nex.f=nex.g+f[nex.x];///下次的代价+评估函数
q.push(nex);
}
}
return -1;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
init(n);
int u,v,w,k;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
edge1[v].push_back(Node(u,w));
edge2[u].push_back(Node(v,w));
}
scanf("%d%d%d",&u,&v,&k);
spfa(v);
printf("%d\n",Astar(u,v,k));
return 0;
}