题目链接: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. 打通MySQL架构和业务的任督二脉

    目前,在很多OLTP场景中,MySQL数据库都有着广泛的应用,也有很多不同的使用方式.从数据库的业务需求.架构设计.运营维护.再到扩容迁移,不同的MySQL架构有不同的特点,适应一定的业务场景,或者解 ...

  2. C++中 线程函数为静态函数 及 类成员函数作为回调函数

    线程函数为静态函数: 线程控制函数和是不是静态函数没关系,静态函数是在构造中分配的地址空间,只有在析构时才释放也就是全局的东西,不管线程是否运行,静态函数的地址是不变的,并不在线程堆栈中static只 ...

  3. 【Linux】linux/unix下telnet提示Escape character is '^]'的意义

    在linux/unix下使用telnet hostname port连接上主机后会提示Escape character is '^]' 这个提示的意思是按Ctrl + ] 会呼出telnet的命令行, ...

  4. [AaronYang]那天有个小孩跟我说Js正则

    按照自己的思路学习Node.Js 随心出发.突破正则冷门知识点,巧妙复习正则常用知识点 标签:AaronYang  茗洋  Node.Js 正则 Javascript 本篇博客地址:http://ww ...

  5. C++11 列表初始化

    在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段多种多样,比如说对于一个数组我们可以使用 int arr[] = {1,2,3}的方式初始化,又比如对于一个简单的结构体: ...

  6. vue弹框,删除元素

    1.效果 2.index.html <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  7. openfire接收离线消息

    先接收离线消息后再通知openfire上线 //获取离线消息 OfflineMessageManager offlineMessageManager=new OfflineMessageManager ...

  8. PHP可变参数

    0x00 缘起 在laravel的源码里经常可以看到下面的函数形式 $func(...$args) 0x01 可变参数旧写法 这表示$func支持可变参数,在php5.6之前则是在函数体内调用 fun ...

  9. Java编程的逻辑 (78) - 线程池

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  10. 【转】Web前端性能优化——如何提高页面加载速度

    前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个“Duang”的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒, ...