zoukankan      html  css  js  c++  java
  • 【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
    ",ans);
    109     return 0;
    110 }
     
  • 相关阅读:
    使用echo $? 查看命令成功执行的原理
    Ubuntu 12.04下NFS安装配置图解
    使用nfsstat命令查看NFS服务器状态
    ORACLE 中rownum和row_number()的使用区别(可指定取sql结果集的第几个数据)
    toad调用存储过程,存储过程调用sql 类
    指纹协查统计sql
    oracle 解锁表
    【转】经典排序算法
    wget 命令用法详解
    Linux 带宽、CPU、内存占用情况
  • 原文地址:https://www.cnblogs.com/xkui/p/4564882.html
Copyright © 2011-2022 走看看