首页 > 代码库 > 【BZOJ1598】牛跑步 [A*搜索]

【BZOJ1598】牛跑步 [A*搜索]

牛跑步

Time Limit: 10 Sec  Memory Limit: 162 MB
[Submit][Status][Discuss]

Description

  BESSIE准备用从牛棚跑到池塘的方法来锻炼.
  但是因为她懒,她只准备沿着下坡的路跑到池塘, 然后走回牛棚.
  BESSIE也不想跑得太远,所以她想走最短的路经.
  农场上一共有M 条路, 每条路连接两个用1..N标号的地点.
  更方便的是,如果X>Y,则地点X的高度大于地点Y的高度.
  地点N是BESSIE的牛棚;地点1是池塘.
  很快, BESSIE厌倦了一直走同一条路.所以她想走不同的路,更明确地讲,她想找出K条不同的路经.为了避免过度劳累,她想使这K条路经为最短的K条路经.
  请帮助BESSIE找出这K条最短路经的长度.
  你的程序需要读入农场的地图,一些从X_i到Y_i 的路经和它们的长度(X_i, Y_i, D_i).

Input

  第1行: 3个数: N, M, 和K
  第 2..M+1行: 第 i+1 行包含3个数 X_i, Y_i, 和 D_i, 表示一条下坡的路.

Output

  第1..K行: 第i行包含第i最短路经的长度,或-1如果这样的路经不存在.如果多条路经有同样的长度,请注意将这些长度逐一列出.

Sample Input

  5 8 7
  5 4 1
  5 3 1
  5 2 1
  5 1 1
  4 3 4
  3 1 1
  3 2 1
  2 1 1

Sample Output

  1
  2
  2
  3
  6
  7
  -1

HINT

  1 <= M <= 10,000, 1 <= N <= 1000, 1 <= K <= 100

 

Main idea

  给定一张图,输出1~k短路的距离。

Solution

  既然是求k短路,那我们使用A*搜索,先反向建图,记录终点到每一个点的最短路,然后把这个dist当做估价来跑A*即可。可以证明:第k次搜到的路即是k短路

Code

技术分享
  1 #include<iostream>    2 #include<string>    3 #include<algorithm>    4 #include<cstdio>    5 #include<cstring>    6 #include<cstdlib>    7 #include<cmath>  8 #include<queue>  9 using namespace std; 10 typedef long long s64; 11   12 const int ONE = 2e6+5; 13   14 int n,m,k; 15 int S,T; 16 int dist[ONE],vis[ONE],Output[ONE],tou,wei; 17 int next[ONE],first[ONE],go[ONE],w[ONE],tot; 18 int Ans[ONE],num; 19   20 struct point 21 { 22         int x,y,z; 23 }a[ONE]; 24   25 struct power 26 { 27         int x,real,eva; 28         bool operator <(const power &a) const 29         { 30             return a.real + a.eva < real + eva; 31         } 32 }; 33   34 inline int get() 35 { 36         int res=1,Q=1;  char c; 37         while( (c=getchar())<48 || c>57) 38         if(c==-)Q=-1; 39         if(Q) res=c-48;  40         while((c=getchar())>=48 && c<=57)  41         res=res*10+c-48; 42         return res*Q;  43 } 44   45 void Add(int u,int v,int z) 46 { 47         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  w[tot]=z; 48 } 49   50 void SPFA(int x) 51 { 52         int q[10000001]; 53         memset(dist,63,sizeof(dist)); 54         tou = 0; wei = 1; 55         vis[x] = 1; dist[x] = 0; q[1] = x; 56         while(tou < wei) 57         { 58             int u = q[++tou]; 59             for(int e=first[u];e;e=next[e]) 60             { 61                 int v = go[e]; 62                 if(dist[v] > dist[u] + w[e]) 63                 { 64                     dist[v] = dist[u] + w[e]; 65                     if(!vis[v]) vis[v] = 1, q[++wei] = v; 66                 } 67             } 68             vis[u] = 0; 69         } 70 } 71   72 void Astar() 73 { 74         priority_queue <power> q; 75         q.push( (power){S, 0, dist[S]} ); 76         while(!q.empty()) 77         { 78             power u = q.top();  q.pop(); 79             if(u.x == T) Ans[++num] = u.real; 80             if(++Output[u.x] > k) continue; 81             if(Output[T] == k) return; 82             for(int e=first[u.x]; e; e=next[e]) 83             { 84                 int v=go[e]; 85                 q.push( (power){v, u.real+w[e], dist[v]} ); 86             } 87         } 88 } 89   90 int main() 91 { 92         n=get();    m=get();    k=get(); 93         S=n,    T=1; 94         for(int i=1;i<=m;i++) 95         { 96             a[i].x=get();   a[i].y=get();   a[i].z=get(); 97             Add(a[i].y, a[i].x, a[i].z); 98         } 99         SPFA(T);100          101         memset(first,0,sizeof(first));  tot=0;102         for(int i=1;i<=m;i++) Add(a[i].x,a[i].y,a[i].z);103          104         Astar();105          106         for(int i=1;i<=k;i++)107             printf("%d\n",Ans[i]!=0?Ans[i]:-1);108          109 }
View Code

 

【BZOJ1598】牛跑步 [A*搜索]