http://poj.org/problem?id=2449
K短路的定义:
1.如果起点终点相同,那么0并不是最短路,而是要出去一圈回来之后才是最短路,那么第K短路也是一样。
2.每个顶点和每条边都可以使用多次。(可以存在环和来回走)
给定起终点,求K短路的长度
然后求K短路使用A*算法,其估价函数f(n) = g(n)+h(n),h(n)是终点到结点n的最短路径,g(n)是起点到结点n的实际代价, 这样选择显然能满足A*估价函数的要求,g(n)>=g'(n),
h(n)<=h'(n)。
h(n)可以对原图的逆图进行SPFA得出。
终止条件是,如果终点第K次出队的话,那么表明已经找到第K短路。
注意处理起点终点不连通的情况。
#pragma comment(linker, "/STACK:36777216") #pragma GCC optimize ("O2") #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <map> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define clr0(x) memset(x,0,sizeof(x)) #define clr1(x) memset(x,-1,sizeof(x)) #define eps 1e-9 const double pi = acos(-1.0); typedef long long LL; typedef unsigned long long ULL; const int modo = 1e9 + 7; const int INF = 0x3f3f3f3f; const int inf = 0x3fffffff; const int maxn = 1005,maxm = 100005; struct edge{ int v,w,next; edge(){}; edge(int vv,int ww,int nnext):v(vv),w(ww),next(nnext){}; }e[maxm<<1]; struct node{ int f,g,v; node(){}; node(int ff,int gg,int vv):f(ff),g(gg),v(vv){}; bool operator < (const node &a) const{ return a.f < f; } }; int head[maxn],tail[maxn],dist[maxn],inq[maxn]; int n,m,s,t,k,ecnt; void init() { clr1(head),clr1(tail); ecnt = 0; fill(dist,dist+maxn,inf); clr0(inq); } void add(int u,int v,int w) { e[ecnt] = edge(v,w,head[u]); head[u] = ecnt++; e[ecnt] = edge(u,w,tail[v]); tail[v] = ecnt++; } void spfa(int src) { queue<int> q; q.push(src);dist[src] = 0,inq[src] = 1; while(!q.empty()){ int cur = q.front(); q.pop();inq[cur] = 0; for(int i = tail[cur];i != -1;i = e[i].next){ int nxt = e[i].v; if(dist[nxt] > dist[cur] + e[i].w){ dist[nxt] = dist[cur] + e[i].w; if(!inq[nxt]) inq[nxt] = 1,q.push(nxt); } } } } int Astar(int src,int dst){ priority_queue<node> q; if(dist[src] == inf) return -1; clr0(inq); q.push(node(dist[src],0,src)); while(!q.empty()){ node cur = q.top(); q.pop(); inq[cur.v]++; if(inq[dst] == k) return cur.f; if(inq[cur.v] > k) continue; for(int i = head[cur.v];i != -1;i = e[i].next){ node nxt(dist[e[i].v] + e[i].w + cur.g,e[i].w + cur.g,e[i].v); q.push(nxt); } } return -1; } int main(){ int u,v,w; while(~RD2(n,m)){ init(); while(m--){ RD3(u,v,w);u--,v--; add(u,v,w); } RD3(s,t,k);s--,t--; spfa(t); if(s == t)//如果起点终点相同,0不是第1短路径。。 k++; printf("%d ",Astar(s,t)); } return 0; }