【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 }
时间: 2024-10-23 15:09:11

【k短路&A*算法】BZOJ1975: [Sdoi2010]魔法猪学院的相关文章

[BZOJ1975][SDOI2010]魔法猪学院(k短路,A*)

1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2748  Solved: 883[Submit][Status][Discuss] Description iPig 在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了 解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒……. 能量守恒……iPig

BZOJ1975 [SDOI2010] 魔法猪学院

[问题描述] iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很 多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒--. 能量守恒--iPig 今天就在进行一个麻烦的测验.iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量.作为 PKU 的顶尖学猪,让 iPig 用最少的能量完成从一种元素转换到另一种元素--等

洛谷P2483 Bzoj1975 [SDOI2010]魔法猪学院

题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒……. 能量守恒……iPig 今天就在进行一个麻烦的测验.iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量.作为 PKU 的顶尖学猪,让 iPig 用最少的能量完成从一种元素转换到另一种元素……等等,i

Bzoj 1975: [Sdoi2010]魔法猪学院 dijkstra,堆,A*,K短路

1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1357  Solved: 446[Submit][Status][Discuss] Description iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒……. 能量守恒……iPig 今

洛谷 P2483 [SDOI2010]魔法猪学院

P2483 [SDOI2010]魔法猪学院 k短路模板 1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=10005; 7 int n,m,s,t,k,num,head1[maxn*100],head2[maxn*100],tot; 8 int nxt1[maxn*100]

[K短路] SDOI2010 魔法猪学院

魔法猪学院 题目背景 感谢@kczno1 @X_o_r 提供hack数据 题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒--. 能量守恒--iPig 今天就在进行一个麻烦的测验.iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量.作为 PKU 的顶尖

P2483 【模板】k短路([SDOI2010]魔法猪学院)

题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒--. 能量守恒--iPig 今天就在进行一个麻烦的测验.iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量.作为 PKU 的顶尖学猪,让 iPig 用最少的能量完成从一种元素转换到另一种元素--等等,i

BZOJ 1975 SDOI2010 魔法猪学院 A*k短路

题目大意:给定一个值E 求起点到终点的最多条路径 使长度之和不超过E k短路的A*算法--每一个点有一个估价函数=g[x]+h[x] 当中g[x]是从源点出发已经走了的长度 h[x]是从这个点到汇点的最短路 首先先在反图上跑一遍SPFA求出每一个点的h[x],然后将源点的g[x]+h[x]增加堆 每次取出堆顶时将堆顶的g[x]向所连接的边扩展 第k次取出汇点即是答案 当中有一个剪枝就是当第k+1次取出某个点时不继续拓展 防止MLE 可是这里k未知 我们能够对k进行估价处理 初始k=floor(E

BZOJ 1975: [Sdoi2010]魔法猪学院 大水题 第k短路 spfa

https://www.lydsy.com/JudgeOnline/problem.php?id=1975 我好像到现在了第k短路都不会写,mdzz. 先spfa求出最短路,然后扫点存各种前置路径已经决定的最短路,小根堆暴力即可. 有向图要存反向边,写完才发现的,临时添成两种了,丑也没办法 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #