题目链接:http://poj.org/problem?id=3635

题意题解等均参考:POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]

一些口胡:

说实话,上次写类似的二维状态最短路Gym 101873C - Joyride - [最短路变形][优先队列优化Dijkstra],我没能把手写二叉堆优化Dijkstra的给写出来。

这次费了点功夫,也算是给写出来了,需要注意的点还是有点多的。而且我终于深刻理解为啥不推荐手写二叉堆了,主要是代码量相比优先队列实在是有点大……

而且耗时好像和优先队列优化Dijkstra没啥差别。

AC代码:

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e3+;
const int maxm=1e4+;
const int maxc=+; int n,m,q;
int p[maxn]; struct Edge{
int u,v,w;
Edge(int _u=,int _v=,int _w=){u=_u,v=_v,w=_w;}
};
vector<Edge> E;
vector<int> G[maxn];
void init(int l,int r)
{
E.clear();
for(int i=l;i<=r;i++) G[i].clear();
}
void addedge(int u,int v,int w)
{
E.push_back(Edge(u,v,w));
G[u].push_back(E.size()-);
} int d[maxn][maxc],vis[maxn][maxc];
struct Hnode{
int v,r;
Hnode(){}
Hnode(int _v,int _r) {
v=_v, r=_r;
}
};
struct Heap
{
int sz;
Hnode hp[*maxn*maxc];
int pos[maxn][maxc];
void up(int now)
{
while(now>)
{
int par=now>>;
if(d[hp[now].v][hp[now].r]<d[hp[par].v][hp[par].r]) //子节点小于父节点,不满足小顶堆性质
{
swap(hp[par],hp[now]);
swap(pos[hp[par].v][hp[par].r],pos[hp[now].v][hp[now].r]);
now=par;
}
else break;
}
}
void push(Hnode x) //插入权值为x的节点
{
hp[++sz]=x;
pos[x.v][x.r]=sz;
up(sz);
}
Hnode top(){return hp[];}
void down(int now)
{
while((now<<)<=sz)
{
int nxt=now<<;
if(nxt+<=sz && d[hp[nxt+].v][hp[nxt+].r]<d[hp[nxt].v][hp[nxt].r]) nxt++; //取左右子节点中较小的
if(d[hp[nxt].v][hp[nxt].r]<d[hp[now].v][hp[now].r]) //子节点小于父节点,不满足小顶堆性质
{
swap(hp[now],hp[nxt]);
swap(pos[hp[now].v][hp[now].r],pos[hp[nxt].v][hp[nxt].r]);
now=nxt;
}
else break;
}
}
void pop() //移除堆顶
{
hp[]=hp[sz--];
pos[hp[].v][hp[].r]=;
down();
}
inline void clr()
{
sz=;
memset(pos,,sizeof(pos));
}
}H;
int dijkstra(int c,int s,int t)
{
memset(d,0x3f,sizeof(d));
memset(vis,,sizeof(vis)); H.clr();
d[s][]=, H.push((Hnode){s,});
while(H.sz)
{
int u=H.top().v, r=H.top().r; H.pop();
if(u==t) return d[u][r];
if(vis[u][r]) continue;
else vis[u][r]=; if(r<c) {
d[u][r+]=d[u][r]+p[u], H.push((Hnode){u,r+});
}
for(int i=;i<G[u].size();i++)
{
Edge &e=E[G[u][i]]; int v=e.v;
if(r<e.w || vis[v][r-e.w]) continue;
if(d[v][r-e.w]>d[u][r]) {
d[v][r-e.w]=d[u][r];
if(H.pos[v][r-e.w]) H.up(H.pos[v][r-e.w]);
else H.push((Hnode){v,r-e.w});
}
}
}
return INF;
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++) scanf("%d",&p[i]);
init(,n);
for(int i=,u,v,w;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
scanf("%d",&q);
for(int i=,c,s,t;i<=q;i++)
{
scanf("%d%d%d",&c,&s,&t);
int ans=dijkstra(c,s,t);
if(ans<INF) printf("%d\n",ans);
else printf("impossible\n");
}
}

在百练上面可以使用pb_ds库,所以用在OpenJ_Bailian 3761 - Full Tank?上交了一发配对堆优化的Dijkstra。

如果想自己写结构体类型放进配对堆的话,还要再写一个专门用来比较结构体的类型,里面要重定义"()"操作符。

AC代码:

#include<bits/stdc++.h>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
const int INF=0x3f3f3f3f;
const int maxn=1e3+;
const int maxm=1e4+;
const int maxc=+; int n,m,q;
int p[maxn]; struct Edge{
int u,v,w;
Edge(int _u=,int _v=,int _w=){u=_u,v=_v,w=_w;}
};
vector<Edge> E;
vector<int> G[maxn];
void init(int l,int r)
{
E.clear();
for(int i=l;i<=r;i++) G[i].clear();
}
void addedge(int u,int v,int w)
{
E.push_back(Edge(u,v,w));
G[u].push_back(E.size()-);
} struct Qnode{
int v;
int d,r;
Qnode(){}
Qnode(int _v,int _d,int _r) {
v=_v, d=_d, r=_r;
}
};
struct Cmp{
bool operator()(const Qnode& a,const Qnode& b)const {
return a.d>b.d;
}
};
typedef __gnu_pbds::priority_queue<Qnode,Cmp,pairing_heap_tag> Heap;
int d[maxn][maxc];
int dijkstra(int c,int s,int t)
{
memset(d,0x3f,sizeof(d)); Heap Q;
Heap::point_iterator id[maxn][maxc]; d[s][]=;
id[s][]=Q.push(Qnode(s,d[s][],));
while(!Q.empty())
{
int u=Q.top().v, r=Q.top().r; Q.pop();
if(u==t) return d[u][r];
if(r<c)
{
d[u][r+]=d[u][r]+p[u];
id[u][r+]=Q.push(Qnode(u,d[u][r+],r+));
}
for(int i=;i<G[u].size();i++)
{
Edge &e=E[G[u][i]]; int v=e.v;
if(r<e.w) continue;
if(d[v][r-e.w]>d[u][r])
{
d[v][r-e.w]=d[u][r];
if(id[v][r-e.w]!=) Q.modify(id[v][r-e.w],Qnode(v,d[v][r-e.w],r-e.w));
else id[v][r-e.w]=Q.push(Qnode(v,d[v][r-e.w],r-e.w));
}
}
}
return INF;
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++) scanf("%d",&p[i]);
init(,n);
for(int i=,u,v,w;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
scanf("%d",&q);
for(int i=,c,s,t;i<=q;i++)
{
scanf("%d%d%d",&c,&s,&t);
int ans=dijkstra(c,s,t);
if(ans<INF) printf("%d\n",ans);
else printf("impossible\n");
}
}

POJ 3635 - Full Tank? - [最短路变形][手写二叉堆优化Dijkstra][配对堆优化Dijkstra]的更多相关文章

  1. POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]

    题目链接:http://poj.org/problem?id=3635 Description After going through the receipts from your car trip ...

  2. POJ 3635 Full Tank? 【分层图/最短路dp】

    任意门:http://poj.org/problem?id=3635 Full Tank? Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  3. Full Tank? POJ - 3635 (bfs | 最短路)

    After going through the receipts from your car trip through Europe this summer, you realised that th ...

  4. POJ 2253 Frogger【最短路变形——路径上最小的最大权】

    链接: http://poj.org/problem?id=2253 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...

  5. poj 3635 Full Tank? ( bfs+dp思想 )

    Full Tank? Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5857   Accepted: 1920 Descri ...

  6. poj 3635 Full Tank? ( 图上dp )

    题意: 已知每一个点的加油站的油价单位价格(即点权).每条路的长度(边权). 有q个询问.每一个询问包含起点s.终点e和油箱容量. 问从起点走到终点的最小花费.假设不可达输出impossible,否则 ...

  7. POJ 1797 Heavy Transportation 最短路变形(dijkstra算法)

    题目:click here 题意: 有n个城市,m条道路,在每条道路上有一个承载量,现在要求从1到n城市最大承载量,而最大承载量就是从城市1到城市n所有通路上的最大承载量.分析: 其实这个求最大边可以 ...

  8. [POJ 3635] Full Tank?

    题目 Description 已知每个点的加油站的油价单价(即点权),每条路的长度(边权). 有q个询问,每个询问包括起点s.终点e和油箱容量c. 问从起点走到终点的最小花费.如果不可达输出impos ...

  9. POJ 2253 Frogger【最短路变形/最小生成树的最大权/最小瓶颈树/A到B多条路径中的最小的最长边】

    Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sit ...

随机推荐

  1. (原)MobileNetV2

    转载请注明出处: https://www.cnblogs.com/darkknightzh/p/9410574.html 论文: MobileNetV2: Inverted Residuals and ...

  2. vbox磁盘空间如何扩容

    vbox磁盘空间如何扩容   为虚拟机硬盘扩容(Oracle VM VirtualBox) VBoxManage modifyhd         <uuid>|<filename& ...

  3. 使用Kotlin优雅的开发Android应用

    来源:https://juejin.im/post/5915c0a744d904006c4e3bcd demo下载地址:https://github.com/xiehui999/KotlinForAn ...

  4. Swift 弱引用与无主引用

    前言 Swift 提供了两种解决循环引用的方法,弱引用和无主引用. 弱引用和无主引用可以使循环中的一个实例引用另一个实例时不使用强引用. 1.弱引用 对生命周期中会变为 nil 的实例采用弱引用,也就 ...

  5. 12C配置EM Express的https端口

    1.启动监听并查看监听信息 $ lsnrctl stat ora12 LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 07-FEB-2017 ...

  6. iptabes一条指令开放多个端口

    开放某个范围段内的端口: -A INPUT -p tcp -m state --state NEW -m tcp --dport 9001:9009 -j ACCEPT 开放多个不连续的端口: -A ...

  7. 游戏编程精粹学习 - 使用Bloom过滤来提高计算性能(BloomFilter)

    原文在<游戏编程精粹2>的1.2中,BloomFilter是一种可以快速检测是否存在集合包含关系的数据结构,但有一定的误识别率. 该结构的优点 判断包含关系时效率较高,粗略测试了下比Lis ...

  8. iOS之加载Gif图片

    Gif图片是非常常见的图片格式,尤其是在聊天的过程中,Gif表情使用地很频繁.但是iOS竟然没有现成的支持加载和播放Gif的类. 简单地汇总了一下,大概有以下几种方法: 一.加载本地Gif文件 1.使 ...

  9. hdoj:2035

    #include <iostream> using namespace std; int main() { long a, b; && b != ) { long resu ...

  10. 【Ansible】的python api

    [Ansible API] Ansible本身就是由python写成,所有其对python形式的API的支持应该不错. 其API分不同的版本,这个版本也就是ansible本身的版本,可以通过ansib ...