pku 2449

题目连接:http://acm.pku.edu.cn/JudgeOnline/problem?id=2449

题意:求出给定起点到终点的第k条最短路径。。。

一开始看题只能大概知道怎么搜吧。。。但是实现的时候困难重重,很有可能会死循环,后来看了一牛人的博客,才知道用A*启发式搜索,首先用Dijkstra得到终点到任何一点的最短距离,做为启发函数,好后维护一个优先队列 求第K段路径。。。。

注意:当起点和终点是同一点时,也是一条路径 所以k++;

代码:

#include<iostream> #include<vector> #include<queue> #include<stdio.h> using namespace std; const int MAXN=1005; const int INF=999999999; int D[MAXN],visit[MAXN],C[MAXN]; struct node { int id; int len; node(int v,int l):id(v),len(l){} inline bool operator<(const node &b)const {//用来维护有限队列的, return D[id]+len>D[b.id]+b.len; } }; int n,m,S,T,K; vector<node>g[MAXN]; vector<node>map[MAXN]; void Dijkstra() { priority_queue<node>Q; for(int i=1;i<=n;i++){D[i]=INF;visit[i]=0;C[i]=0;} D[T]=0; Q.push(node(T,0)); while(!Q.empty()) { int u=Q.top().id; Q.pop(); if(visit[u]) continue; visit[u]=1; for(int i=0;i<map[u].size();i++) { int v=map[u][i].id; if(!visit[v]&&D[v]>D[u]+map[u][i].len) { D[v]=D[u]+map[u][i].len; Q.push(node(v,D[v])); } } } } int A_star() { priority_queue<node>Q; if(D[S]==INF) return -1; Q.push(node(S,0)); while(!Q.empty()) { int u=Q.top().id; int len=Q.top().len; Q.pop(); C[u]++; if(C[T]==K) return len; if(C[u]>K) continue; //如果一个点在到终点途中,那么经过这个点的次数不可能超过k次, //如果超过k次了,那么完全可以找到一条只经过k的更短的路径,所以这点必不在途中 所以没有必要再对它松弛 for(int i=0;i<g[u].size();i++) { int v=g[u][i].id; Q.push(node(v,len+g[u][i].len)); } } return -1; } int main() { while(scanf("%d %d",&n,&m)!=EOF) { int a,b,time; for(int i=0;i<m;i++) { scanf("%d %d %d",&a,&b,&time); g[a].push_back(node(b,time)); map[b].push_back(node(a,time)); } scanf("%d %d %d",&S,&T,&K); if(S==T) K++; Dijkstra(); printf("%d/n",A_star()); } return 0; }

 

你可能感兴趣的:(c,struct)