NEU 1664 传送(最短路基础 堆优化Dijkstra)
题目描述
小A最近喜欢上一款游戏:游戏把地图分了一些区域,这些区域可能会重叠,也可能不会。
游戏中有一项传送技能,改传送技能只能将在同一区域的两个地方使用。小A可以利用区域中重叠部分来实现从某一区域到另一个区域的移动。
当然技能会消耗魔法值,对于同一区域内两点,消耗的魔法值是相同的。如下图:
有红蓝两个区域,共4个地点1 2 3 4,假设在红色区域移动只需消耗a1点魔法值,在蓝色区域间移动需花费a2点魔法值,那么1和2之间或者1和3之间都需花费a1点魔法,2和4或者3和4之间都需要a2点魔法,2和3之间选择消耗a1点魔法也可以选择消耗a2点魔法。
现在小A在S点接到了一个任务,需要到达F点去做任务,再到P点交任务。
现在让你求一下完成该任务,需要因为传送消耗的魔法值至少为多少。
当然有些地方需要花RMB才能到达,即你从S点无论如何也无法到达F点去做任务,或者F点无法到达P点。因为双11,小A已经没有RMB了,这是你只需告诉他“Poor guy, you don’t have enough Money!”。
输入
多组样例输入(不会超过10组)
对于每一组样例:
第一行有五个整数 n m S F P 表示有n个地点和m个区域(2<=n<=100000) (0<m<1000000)。S F P为题目中所述的地点编号。(地点编号为:1,2,3......,n).
接下来每行描述的是每一个区域的信息,
ai bi 表示 在第i块区域内需要消耗ai点魔法值,第i各区域有bi个地点,然后有bi个数,代表第i个区域内第地点编号。(1<=ai<=1000000000, bi>0) .
保证所有bi的和小于1000000.
输出
如果无解,则输出“Poor guy, you don’t have enough Money!”(引号中的内容)。
否则就输出最少的消耗的魔法量。
样例输入
4 2 1 4 2
3 3 1 2 3
5 3 2 3 4
样例输出
13 思路:把区域当做节点,穿过某个区域抽象成路过某个节点,进入该节点话费为ai,出节点免费,链接点和区域,然后以目标点(中间点)为原点做一遍单源最短路,我用的是Dijkstra,最后时间为7000+ms,空间为50000kb+,空间还好,是提交的里面几乎最小的,但是时间很不满意,应该还有更好的方法,知道了来更新。
(update001:下面这个是错误代码,不要参考)
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
const int maxl=;
const int maxn=;
using namespace std;
int n,m,s,t,p;
int lin[maxn],cnt=;
struct str
{
int y;
int z;
int next;
}e[maxl];
void insert(int x,int y,int z)
{
cnt++;
e[cnt].next=lin[x];
lin[x]=cnt;
e[cnt].y=y;
e[cnt].z=z;
}
struct strdis
{
int x;
long long dis;
bool operator<(const strdis& a)const{return dis<a.dis;}
void set(int xx,int diss){x=xx;dis=diss;}
}temp,noww;
//bool operator <(const strdis &a,const strdis &b){return a.dis<b.dis;}
priority_queue <strdis> q;
bool vis[maxn];
long long dis[maxn];
int main()
{
while(scanf("%d%d%d%d%d",&n,&m,&s,&p,&t)!=EOF)
{
memset(lin,,sizeof(lin));cnt=;
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++)
{
int ai,bi,x;
scanf("%d%d",&ai,&bi);
for(int j=;j<=bi;j++)
{
scanf("%d",&x);
insert(x,n+i,ai);
insert(n+i,x,);
}
}
temp.set(p,);
q.push(temp);
memset(dis,0x3f,sizeof(dis));
dis[p]=;
while(!q.empty())
{
noww=q.top();
q.pop();
int nn=noww.x;
if(vis[nn])continue;
vis[nn]=;
for(int i=lin[nn];i;i=e[i].next)
{
int u=e[i].y;
if(dis[u]>dis[nn]+e[i].z)
{
dis[u]=dis[nn]+e[i].z;
temp.set(u,dis[u]);
q.push(temp);
}
}
}
if((!vis[s])||(!vis[t]))
{
printf("Poor guy, you don't have enough Money!\n");
}
else
{
printf("%lld\n",dis[s]+dis[t]);
}
} return ;
}
Dijkstra
提交了五次,前两次是忘记去掉打表。。。第三次是复制粘贴的答案字符串里面有不对的字符,第四次是重定义符号弄反了,第五次是没有看到多组数据。
恩,re小王子又回来了。。。。要注意。
哦,既然写了Dijkstra,就要说下如何堆优化,
其实不用担心如何更新堆里边dis的值,没必要,只需要把新的值push进去就好了,因为访问次优的时候,那个点已经vis过了。。。就是空间上浪费点儿。。。不知道怎么解决
update-------------------------------------------------------------------------------------2016.02.11
我的代码比别人的慢四倍,自己怎么找都找不到问题,学长一下就看了出来。。。
原来的代码有一个符号错了,就是重定义小于号那里,因为默认是大根堆,也就是最大的先出来,我们需要最短的,于是需要反着定义
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
const int maxl=;
const int maxn=;
using namespace std;
int n,m,s,t,p;
int lin[maxn],cnt=;
struct str
{
int y;
int z;
int next;
}e[maxl];
void insert(int x,int y,int z)
{
cnt++;
e[cnt].next=lin[x];
lin[x]=cnt;
e[cnt].y=y;
e[cnt].z=z;
}
struct strdis
{
int x;
long long dis;
bool operator<(const strdis& a)const{return dis>a.dis;}
}noww;
//bool operator <(const strdis &a,const strdis &b){return a.dis<b.dis;}
priority_queue <strdis> q;
bool vis[maxn];
long long dis[maxn];
int main()
{
while(scanf("%d%d%d%d%d",&n,&m,&s,&p,&t)!=EOF)
{
memset(lin,,sizeof(lin));cnt=;
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++)
{
int ai,bi,x;
scanf("%d%d",&ai,&bi);
for(int j=;j<=bi;j++)
{
scanf("%d",&x);
insert(x,n+i,ai);
insert(n+i,x,);
}
}
q.push((strdis){p,});
memset(dis,0x3f,sizeof(dis));
dis[p]=;
while(!q.empty())
{
noww=q.top();
q.pop();
int nn=noww.x;
if(vis[nn])continue;
vis[nn]=;
for(int i=lin[nn];i;i=e[i].next)
{
int u=e[i].y;
if(dis[u]>dis[nn]+e[i].z)
{
dis[u]=dis[nn]+e[i].z;
q.push((strdis){u,dis[u]});
}
}
}
if((!vis[s])||(!vis[t]))
{
printf("Poor guy, you don't have enough Money!\n");
}
else
{
printf("%lld\n",dis[s]+dis[t]);
}
} return ;
}
NEU 1664 传送(最短路基础 堆优化Dijkstra)的更多相关文章
- BZOJ 3040 最短路 (堆优化dijkstra)
这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...
- 最短路模板|堆优化Dijkstra,SPFA,floyd
Ⅰ:Dijkstra单源点最短路 1.1Dijkstra const int MAX_N = 10000; const int MAX_M = 100000; const int inf = 0x3f ...
- POJ 3635 - Full Tank? - [最短路变形][手写二叉堆优化Dijkstra][配对堆优化Dijkstra]
题目链接:http://poj.org/problem?id=3635 题意题解等均参考:POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]. 一些口胡: ...
- 【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost
[题目大意] 给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案. [思路] 在堆优化Dijkstra中,用pre记录前驱.如果新方案 ...
- 堆优化Dijkstra计算最短路+路径计数
今天考试的时候遇到了一道题需要路径计数,然而蒟蒻从来没有做过,所以在考场上真的一脸懵逼.然后出题人NaVi_Awson说明天考试还会卡SPFA,吓得我赶紧又来学一波堆优化的Dijkstra(之前只会S ...
- PAT-1030 Travel Plan (30 分) 最短路最小边权 堆优化dijkstra+DFS
PAT 1030 最短路最小边权 堆优化dijkstra+DFS 1030 Travel Plan (30 分) A traveler's map gives the distances betwee ...
- 【bzoj4070】[Apio2015]雅加达的摩天楼 set+堆优化Dijkstra
题目描述 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 “doge” 的神秘生物 ...
- UVA - 11374 - Airport Express(堆优化Dijkstra)
Problem UVA - 11374 - Airport Express Time Limit: 1000 mSec Problem Description In a small city c ...
- BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...
随机推荐
- 使用新的CSS类型对象模型
el.attributeStyleMap.set('padding', CSS.px(42)); const padding = el.attributeStyleMap.get('padding') ...
- css3动画简单案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- javascript中的原型对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Android WiFi热点完全研究(自定义创建、跳转系统界面设置、读取配置、切换,Android6.0适配)
前言: WiFi热点设置页面的安全性选项在Android 4.x上有“无”.“WPA PSK”.“WPA2 PSK”三个选项,在Android 5.0(含)之后去掉了WPA PSK选项(部分手机厂家会 ...
- sql中数据库连接与断开式连接有什么区别?
连接式指的是对数据的操作在 conn.Open() 与 conn.Close()之间: 断开式连接指的是 conn.Open()打开连接之后,先将数据放入adapter中,然后关闭连接(conn.Cl ...
- 【Five-Minute Share】数据库内存分配设置
对于数据库分配的内存,经常会看到的一条准则是:将服务器75-80%的内存分配给数据库.这是一条比较常见的准则,但并不是绝对的.首先,我们需要保障操作系统运行本身所需的充足内存后,才能去考虑数据库所分配 ...
- 写给VC++ Windows开发的初学者 一片不错的博文
不知不觉2010年都过了半年了,想来我学C语言已经12个年头了(从1998年开始),用VC++也有11年了,最早使用Turbo C2.0 ,也学过汇编,后来使用Borland C++3.0 .Micr ...
- UVa340(Master-Mind Hints)未完成
#include<stdio.h> int main() { int num,a[100],i,j,b[100]; while(scanf("%d",&num) ...
- MindManager 2019新版上市 ,了解一下!
所有的等待都是值得的!MindManager在蓄力一年后,给各位思维导图爱好者带来了全新的MindManager 2019 for Windows.全新的版本包含英语.德语.法语.俄语.中文.日语,新 ...
- 347. 前K个高频元素
题目描述 给定一个非空的整数数组,返回其中出现频率前 k 高的元素. 示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums = ...