暴力做法:bfs,当搜索到目标点K次时,结束操作。
思路:由于此题数据范围过大,不能利用bfs,进行无脑宽搜,为了减少搜索量,尽可能早的搜索到目标点,此时需要用到A*算法。当搜索到目标点K次时,则为答案。
估价函数:注意估价函数不能大于未来实际代价,所以可以设计估价函数为:该点到目标点的最短距离,可以利用反向建边,Dijkstra算法求解。
ac代码:
#include<iostream>
#include<map>
#include<queue>
#include<cstring>
using namespace std;
const int N = 100005;
typedef pair<int,int> PII;
struct edge{
int v,w,ne;
}e[N];
int h[N],idx,d[N],vis[N];//d[i]表示i点距离终点end的最短距离
int n,m;
int start,endd,K;//起点和终点和K
void add(int a,int b,int w){
e[idx].v = b;
e[idx].w = w;
e[idx].ne = h[a];
h[a] = idx++;
}
edge e1[N];
int h1[N],idx1;//d[i]表示i点距离终点end的最短距离
void add1(int a,int b,int w){
e1[idx1].v = b;
e1[idx1].w = w;
e1[idx1].ne = h1[a];
h1[a] = idx1++;
}
//用dijkstra求出来每个点距离终点的最短距离
void dij(int x){
int i,cnt = 0;
priority_queue<PII,vector<PII>,greater<PII> > q;
memset(d,0x3f,sizeof d);
d[x] = 0;
q.push({d[x],x});
while(!q.empty()){
PII t = q.top();q.pop();
int a = t.first,b = t.second;
//如果当前点已经求出来最小距离,continue
if(vis[b] == 1) continue;
cnt++;
vis[b] = 1;
if(cnt == n) break;
for(i = h1[b];i!=-1;i = e1[i].ne){
int v = e1[i].v,w = e1[i].w;
if(vis[v] == 1) continue;
if(d[v] > a+w){
d[v] = a+w;
q.push({d[v],v});
}
}
}
return;
}
int A_star(int x){
int i;int cnt = 0;
priority_queue<PII,vector<PII>,greater<PII> > q;
//估值函数为d[i];
q.push({d[x],x});
while(!q.empty()){
PII t = q.top();q.pop();
int b = t.second;
int a = t.first-d[b];
if(b == endd){
cnt++;
if(cnt == K)
return t.first;
}
for(i = h[b];i!=-1;i = e[i].ne){
int v = e[i].v,w = e[i].w;
q.push({d[v]+a+w,v});
}
}
return -1;
}
int main(){
int i,j;
memset(h,-1,sizeof h);
memset(h1,-1,sizeof h1);
cin>>n>>m;
for(i =1;i<=m;i++){
int a,b,w;
cin>>a>>b>>w;
add(a,b,w);
add1(b,a,w);
}
cin>>start>>endd>>K;
dij(endd);
/*
for(i = 1;i<=n;i++)
cout<<d[i]<<" ";
cout<<endl;
*/
cout<<A_star(start);
return 0;
}