题意:求K短路
先介绍A*算法:
A*算法是一种启发式的搜索,不是纯粹的盲目式搜索,A*算法中有个估价算法g(n),对于每个点而言,都有一个g(n)和h(n)来确定的f(n),实际上就是以f(n)为参考权值来确定搜索的方向,在这里,我们的h(n)表示的是从s点出发到n这个点现在走过的路径长度,而g(n)表示的是从n到e的最短长度的大小,那么就确定了搜索的优先性,这里的A*算法的估价函数g(n)是完美估价,搜索的方向一定是对的。
分析:K短路可以用A*+spfa求。。先求出终点到各个点的最短距离d[1~n],这个变是A*算法的估价函数d[1~n];
建图的时候建一个正向的一个反向的,反向图用来求估价终点到每个点的距离,即为搜索的估价函数。
注意:若s==t,则k++, 因为题目要求必须走过路径。

#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define MAXN 1005 #define INF 1000000000 using namespace std; int n,m,e; struct eee{ int v;//正向图的终止点 int u;//反向图的终止点 int next;//正向图的下一条边 int next1;//反向图的下一条边 int w;//权值 }edge[100*MAXN]; struct node{ int v; int f; int g; bool operator <(const node &a)const{ if(f==a.f)return g>a.g; else return f>a.f; } }; int d[MAXN];//d[v]表示的是终点到v的距离,即估价函数g int first[MAXN],first1[MAXN],vis[MAXN]; priority_queue<node>pq; queue<int> que; void add(int u,int v,int w){ edge[e].u=u; edge[e].w=w; edge[e].v=v; edge[e].next=first[u]; first[u]=e; edge[e].next1=first1[v]; first1[v]=e++; } void init(int n){ memset(first,-1,sizeof(first)); memset(vis,0,sizeof(vis)); memset(first1,-1,sizeof(first1)); e=0; } void spfa(int s){//求估价函数 while(!que.empty())que.pop(); for(int i=1;i<=n;i++)d[i]=INF; d[s]=0;vis[s]=1; que.push(s); while(!que.empty()){ int u=que.front(); que.pop(); vis[u]=0; for(int i=first1[u];i!=-1;i=edge[i].next1){ int v=edge[i].u; if(d[v]>d[u]+edge[i].w){ d[v]=d[u]+edge[i].w; if(!vis[v]){ que.push(v); vis[v]=1; } } } } } int a_start(int s,int t,int k){ while(!pq.empty())pq.pop(); int cnt=0; if(s==t)k++; node a; a.v=s,a.g=0; a.f=a.g+d[s]; pq.push(a); while(!pq.empty()){ node b=pq.top(); pq.pop(); if(b.v==t)cnt++; if(cnt==k)return b.g; for(int i=first[b.v];i!=-1;i=edge[i].next){ int v=edge[i].v; a.g=b.g+edge[i].w; a.f=a.g+d[v]; a.v=v; pq.push(a); } } return -1; } int main() { while(scanf("%d%d",&n,&m)==2){ init(n); int a,b,c; for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); add(a,b,c); } int s,t,k; scanf("%d%d%d",&s,&t,&k); spfa(t); if(d[s]==INF)printf("-1\n"); else printf("%d\n",a_start(s,t,k)); } return 0; }