【k短路&A*算法】BZOJ1975: [Sdoi2010]魔法猪学院

Description

找出1~k短路的长度。
 

Solution

k短路的求解要用到A*算法

A*算法的启发式函数f(n)=g(n)+h(n)

g(n)是状态空间中搜索到n所花的实际代价

h(n)是n到结束状态最佳路径的估计代价

关于h(n)的选取,当h(n)<实际代价时,搜索慢但可出解;h(n)=实际代价时,正确率与效率最高;h(n)>实际代价,快但只能得到近似解。

但在k短路问题中,h(n)是可以选到准确值的,就是n到结束节点的最短路,预处理时从结束节点做一次单源最短路即可。

按广搜的方式扩展节点,每次优先扩展f(n)最小的节点。

第i次扩展到目标节点,代表找到了第i短路。

正确性什么的很好理解。

k短路关于A*部分代码很简洁,用优先队列维护。

 

这道题就是裸题,但这道题很丧病地让proirity_queueMLE,于是要手写堆。

让我这个几乎没手写过堆的STL狗QwQ

 

Code

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<queue>
  4 #include<cstring>
  5 using namespace std;
  6 const int N=5e3+5,M=2e5+5;
  7 
  8 double d[N];
  9 int head[N],e[M],nxt[M],cnt;
 10 double w[M];
 11 int adde(int u,int v,double g){
 12     e[++cnt]=v;w[cnt]=g;nxt[cnt]=head[u];head[u]=cnt;
 13 }
 14 int _head[N],_e[M],_nxt[M],_cnt;
 15 double _w[M];
 16 int _adde(int u,int v,double g){
 17     _e[++_cnt]=v;_w[_cnt]=g;_nxt[_cnt]=_head[u];_head[u]=_cnt;
 18 }
 19 struct node{
 20     double f,g;
 21     int o;
 22     bool operator<(const node&a)
 23         const{return f<a.f;}
 24 };
 25 int n,m;
 26 double c;
 27 
 28 queue<int>q;
 29 int inque[N];
 30 int spfa(){
 31     memset(d,127,sizeof(d));
 32     d[n]=0;
 33     inque[n]=1;
 34     q.push(n);
 35     
 36     while(!q.empty()){
 37         int u=q.front();q.pop();
 38         for(int i=_head[u];i;i=_nxt[i]){
 39             int v=_e[i];
 40             if(d[v]>d[u]+_w[i]){
 41                 d[v]=d[u]+_w[i];
 42                 if(!inque[v]){
 43                     q.push(v);
 44                     inque[v]=1;
 45                 }
 46             }
 47         }
 48         inque[u]=0;
 49     }
 50 }
 51 
 52 int ans,size;
 53 node Q[2000000];
 54 int push(node x){
 55     int now,next;
 56     Q[++size]=x;
 57     now=size;
 58     while(now>1){
 59         next=now>>1;
 60         if(Q[next]<Q[now]) break;
 61         swap(Q[now],Q[next]);
 62         now=next;
 63     }
 64 }
 65 node pop(){
 66     int now,next;
 67     node ret;
 68     ret=Q[1];
 69     Q[1]=Q[size--];
 70     now=1;
 71     while((now<<1)<=size){
 72         next=now<<1;
 73         if(next<size&&Q[next+1]<Q[next]) next++;
 74         if(Q[now]<Q[next]) break;
 75         swap(Q[now],Q[next]);
 76         now=next;
 77     }
 78     return ret;
 79 }
 80 void Astar(){
 81     push((node){d[1],0,1});
 82     while(size){
 83         node x=pop();
 84         for(int i=head[x.o];i;i=nxt[i]){
 85             int v=e[i];
 86             push((node){x.g+w[i]+d[v],x.g+w[i],v});
 87         }
 88         if(x.o==n){
 89             c-=x.f;
 90             if(c<0) return;
 91             ans++;
 92         }
 93     }
 94 }
 95 
 96 int main(){
 97     scanf("%d%d%lf",&n,&m,&c);
 98     int u,v; double g;
 99     for(int i=1;i<=m;i++){
100         scanf("%d%d%lf",&u,&v,&g);
101         adde(u,v,g);
102         _adde(v,u,g);
103     }
104     
105     spfa();
106     Astar();
107     
108     printf("%d\n",ans);
109     return 0;
110 }

 

 
posted @ 2015-06-09 23:24  CyanNode  阅读(1116)  评论(0编辑  收藏  举报