蓝书(算法竞赛进阶指南)刷题记录——POJ2449 Remmarguts' Date(A*求解K短路)

版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/89790181

题目:POJ2449.
题目大意:给定一张 n n 个点 m m 条边的有向图,求 s s t t 的第 k k 短路.
1 n , k 1 0 3 , 1 m 1 0 5 1\leq n,k\leq 10^3,1\leq m\leq 10^5 .

首先考虑直接从堆优化dijkstra拓展,容易发现堆中第 k k 个弹出的到点 x x 的路径长度一定是到点 x x k k 短路,所以我们可以在每次加入元素是不取管三角形不等式的限制直接加入,复杂度 O ( k ( n + m ) log ( n + m ) ) O(k(n+m)\log(n+m)) .

这样子做貌似有些慢,我们考虑用A*优化,在堆中用 f [ x ] [ k ] + d i s [ x ] f[x][k]+dis[x] 作为比较关键字而不是 f [ x ] [ k ] f[x][k] ,其中 f [ x ] [ k ] f[x][k] 表示当前到点 x x 的第 k k 短路, d i s [ x ] dis[x] 表示 x x 到终点的最短路长度.

这样子的话虽然复杂度上界仍然是 O ( k ( n + m ) log ( n + m ) ) O(k(n+m)\log(n+m)) ,但是明显跑不满,实测可以通过.

注意,这道题从起点出发不经过任何边到起点的路径不算,也就是说得特判一下终点为起点的情况,若是这种情况则输出 k + 1 k+1 短路.

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue> 
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=1000,M=100000,INF=(1<<30)-1;

int n,m,s,t,k;
struct side{
  int y,next,v;
}e[M*4+9];
int lin[2][N+9],top;

void Ins(int id,int x,int y,int v){
  e[++top].y=y;e[top].v=v;
  e[top].next=lin[id][x];
  lin[id][x]=top;
}

struct state{
  int x,v;
  state(int X=0,int V=0){x=X;v=V;}
  bool operator > (const state &p)const{return v>p.v;}
};
priority_queue<state,vector<state>,greater<state> >q;
int dis[N+9],use[N+9];

void Dijkstra(int id,int s){
  for (int i=1;i<=n;++i) dis[i]=INF,use[i]=0;
  dis[s]=0;q.push(state(s,0));
  int t;
  while (!q.empty()){
    t=q.top().x;q.pop();
    if (use[t]) continue;
    use[t]=1;
    for (int i=lin[id][t];i;i=e[i].next)
      if (dis[t]+e[i].v<dis[e[i].y]){
        dis[e[i].y]=dis[t]+e[i].v;
        q.push(state(e[i].y,dis[e[i].y]));
	  }
  }
}

int cnt[N+9];

int Astar(int id,int st,int td,int k){
  if (st==td) ++k;
  if (dis[st]==INF) return -1;
  for (int i=1;i<=n;++i) cnt[i]=0;
  q.push(state(st,dis[st]));
  int t,v;
  while (!q.empty()){
  	t=q.top().x;v=q.top().v;q.pop();
  	if (cnt[t]>=k) continue;
  	++cnt[t];
  	if (t==td&&cnt[t]==k) return v;
  	for (int i=lin[id][t];i;i=e[i].next)
  	  if (cnt[e[i].y]<k) q.push(state(e[i].y,v-dis[t]+e[i].v+dis[e[i].y]));
  }
  return -1;
}

Abigail into(){
  scanf("%d%d",&n,&m);
  int x,y,v;
  for (int i=1;i<=m;++i){
    scanf("%d%d%d",&x,&y,&v);
    Ins(0,x,y,v);Ins(1,y,x,v);
  }
  scanf("%d%d%d",&s,&t,&k);
}

Abigail work(){
  Dijkstra(1,t);
}

Abigail outo(){
  printf("%d\n",Astar(0,s,t,k));
}

int main(){
  into();
  work();
  outo();
  return 0;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/89790181