题目大意:给定一张有向图,求某两点间的第k短路。
思路:先用堆优dij处理出各点到终点的最短路距离,然后进行A*,当终点取出次数为k时,第k短路即已求出。
非常要注意的一点是,如果s=t,那么k++。(因为这个不知道被坑了多少回…)
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=1005;
struct edge
{
int to,len;
edge(int to=0,int len=0):to(to),len(len){}
};
struct node
{
int id,cost;
node(int id=0,int cost=0):id(id),cost(cost){}
bool operator < (const node &a) const
{
return cost>a.cost;
}
};
int n,m,s,t,k;
int dis[maxn];
vector<edge> g[maxn],rg[maxn];
void init()
{
memset(dis,0,sizeof(dis));
scanf("%d%d",&n,&m);
while (m--)
{
int a,b,t;
scanf("%d%d%d",&a,&b,&t);
g[a].push_back(edge(b,t));
rg[b].push_back(edge(a,t));
}
scanf("%d%d%d",&s,&t,&k);
if (s==t)
k++;
}
priority_queue<node> q;
bool vis[maxn];
void dijkstra(int s)
{
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push(node(s,0));
while (!q.empty())
{
node tmp=q.top();
int h=tmp.id;
q.pop();
if (vis[h])
continue;
vis[h]=1;
vector<edge>::iterator it;
for (it=rg[h].begin();it!=rg[h].end();++it)
{
if (!vis[(*it).to] && dis[(*it).to]>dis[h]+(*it).len)
{
dis[(*it).to]=dis[h]+(*it).len;
q.push(node((*it).to,dis[(*it).to]));
}
}
}
}
struct atype
{
int now,eva,w;
atype (int now=0,int w=0):now(now),w(w)
{
eva=w+dis[now];
}
bool operator < (const atype &a) const
{
return eva>a.eva;
}
};
int cnt=0,ans=0;
bool flag=0;
priority_queue<atype> aq;
void astar()
{
aq.push(atype(s,0));
while (!aq.empty())
{
atype tmp=aq.top();
aq.pop();
if (tmp.now==t)
{
cnt++;
if (cnt==k)
{
ans=tmp.w;
flag=1;
break;
}
}
vector<edge>::iterator it;
int h=tmp.now;
for (it=g[h].begin();it!=g[h].end();++it)
{
int cost=(*it).len+tmp.w;
atype b=atype((*it).to,cost);
aq.push(b);
}
}
if (flag)
printf("%lld",ans);
else
puts("-1");
}
int main()
{
init();
dijkstra(t);
astar();
return 0;
}