POJ 4046 Sightseeing 枚举+最短路 好题
有n个节点的m条无向边的图,节点编号为1~n
然后有点权和边权,给出q个询问,每一个询问给出2点u,v
输出u,v的最短距离
这里的最短距离规定为:
u到v的路径的所有边权+u到v路径上最大的一个点权的和(点权也可以是u,v)
n<=1000
m<=20000
Q<=20000
时限:5000ms
没有点权的话,好处理
加了点权呢?
我们可以先枚举n个节点,跑n次spfa,当枚举节点u时,我们默认节点u是所有路径上点权最大的一个点
即我们枚举节点u时,我们先把点权比u大的节点删除了,在剩下的图跑spfa
但实际上只要在spfa时加一句判断即可,并不用真的去重建图
这样对于每一个询问,我们只要枚举点权最大的点就可以了,每一个询问是Q(n)
ans=min(dis[i][u]+dis[i][v]+cost[i])
但是这样我还是tle了, 因为这样需要开一个2维数组
dis[i][j]表示以第i个点为起点,到达节点j的短路
最后选择先存下所有询问,离线更新ans,在spfa的同时枚举更新
为什么这样就可以了呢?
因为一维数组比二维数组快很多。
从这道题:
1.当点权和边权混在一起比较难求的时候,我们可以先假设点权最大,分离出点权和边权,再枚举每一个点,就可以了
不止这个, 枚举的思想在很多时候都很好用
2.用stl的queue,时间是4000ms左右,用自己的队列,时间是3500左右,快了半秒
3.一维数组的访问比二维数组快很多
4.做题的时候要注意,循环的时候的终止条件,是到n? m? 还是Q?这个写错就wa了,又难发现
#include<cstdio>
#include<cstring>
#include<algorithm> #define ll long long using namespace std; const int maxn=;
const int maxm=+;
const ll inf=0x3f3f3f3f3f3f3f3f; struct Edge
{
int to,next;
ll w;
};
Edge edge[maxm<<];
int head[maxn];
int tot;
int que[maxm<<];
ll ans[maxm];
int a[maxm];
int b[maxm];
ll dis[maxn];
ll cost[maxn];
bool vis[maxn];
int n,Q; void init()
{
memset(head,-,sizeof head);
tot=;
} void addedge(int u,int v,ll w)
{
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
} void solve(); int main()
{
int m;
while(scanf("%d %d",&n,&m)){
if(!n&&!m)
break; for(int i=;i<=n;i++)
scanf("%lld",&cost[i]);
int u,v;
ll w;
init();
for(int i=;i<=m;i++){
scanf("%d %d %lld",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
scanf("%d",&Q);
for(int i=;i<=Q;i++){
scanf("%d %d",&a[i],&b[i]);
} solve();
}
return ;
} void spfa(int srt)
{
for(int i=;i<=n;i++)
dis[i]=inf;
dis[srt]=;
memset(vis,false,sizeof vis);
int l=,r=;
que[r++]=srt;
vis[srt]=true;
while(l<r){
int u=que[l++];
vis[u]=false;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
ll w=edge[i].w;
if(cost[v]>cost[srt])
continue;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]){
que[r++]=v;
vis[v]=true;
}
}
}
}
for(int i=;i<=Q;i++){
if(dis[a[i]]==inf||dis[b[i]]==inf)
continue;
if(dis[a[i]]+dis[b[i]]+cost[srt]<ans[i])
ans[i]=dis[a[i]]+dis[b[i]]+cost[srt];
}
} void solve()
{
for(int i=;i<=Q;i++)
ans[i]=inf;
for(int i=;i<=n;i++){
spfa(i);
} for(int i=;i<=Q;i++){
if(ans[i]==inf)
printf("-1\n");
else
printf("%lld\n",ans[i]);
}
printf("\n"); return ;
}
POJ 4046 Sightseeing 枚举+最短路 好题的更多相关文章
- POJ 3463 Sightseeing (次短路经数)
Sightseeing Time Limit: 2000MS Memory Limit: 65536K Total Submissions:10005 Accepted: 3523 Descr ...
- hdu 2363(枚举+最短路好题)
Cycling Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- POJ 4046 Sightseeing
Sightseeing Time Limit: 5000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID ...
- POJ 3463 Sightseeing 【最短路与次短路】
题目 Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the ...
- poj1511/zoj2008 Invitation Cards(最短路模板题)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Invitation Cards Time Limit: 5 Seconds ...
- POJ 1637 Sightseeing tour(最大流)
POJ 1637 Sightseeing tour 题目链接 题意:给一些有向边一些无向边,问能否把无向边定向之后确定一个欧拉回路 思路:这题的模型很的巧妙,转一个http://blog.csdn.n ...
- POJ 3621 Sightseeing Cows(最优比例环+SPFA检测)
Sightseeing Cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10306 Accepted: 3519 ...
- poj 1873 凸包+枚举
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6198 Accepted: 1 ...
- HDU 5521.Meeting 最短路模板题
Meeting Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
随机推荐
- Codeforces Round #120 (Div. 2)
A. Vasya and the Bus 根据\(n,m\)是否为0分类讨论下. B. Surrounded 判断两圆是否有交点,否则构造的圆与两圆相切. C. STL 看代码比较清楚. void t ...
- 【NOIP2008】双栈排序
感觉看了题解还是挺简单的,不知道当年chty同学为什么被卡了呢么久--所以说我还是看题解了 原题: Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将 ...
- appium简明教程(6)——启动appium及android模拟器
一般情况下,我们都从命令行启动appium. windows下,dos命令窗口输入 appium 如果该命令报错,那么请重装appium npm install -g appium 如果安装出错,请自 ...
- Linux驱动设计——并发与竞态控制
并发的概念:多个执行单元同时.并行被执行. 共享资源:硬件资源(IO/外设等),软件上的全局变量.静态变量等. 四种并发控制机制(对共享资源互斥的访问):原子操作.自旋锁(spinlock).信号量( ...
- 黑马程序员——JAVA基础之程序控制流结构之判断结构,选择结构
------- android培训.java培训.期待与您交流! ---------- 程序控制流结构:顺序结构:判断结构:选择结构:循环结构. 判断结构:条件表达式无论写成什么样子,只看最终的结构是 ...
- git checkout 和 git checkout --merge <branch_name>使用
一.git checkout //查看当前分支$ git branch master *t2 testing //checkout会覆盖当前工作区文件和覆盖暂存区内容,所以发现分支有未提交的警告,执行 ...
- nginx无法启动: libpcre.so.1/libpcre.so.0: cannot open shared object file解决办法
NGINX启动时提示错误: /usr/local/nginx/sbin/nginx -t/usr/local/nginx/sbin/nginx: error while loading shared ...
- lucene 索引合并策略
在索引算法确定的情况下,最为影响Lucene索引速度有三个参数--IndexWriter中的 MergeFactor, MaxMergeDocs, RAMBufferSizeMB .这些参数无非是控制 ...
- Python_进程、线程及协程
一.Python进程 IO密集型----多线程 计算密集型----多进程 1.单进程 from multiprocessing import Process def foo(i): print('你好 ...
- Openjudge计算概论——数组逆序重放【递归练习】
/*===================================== 数组逆序重放 总时间限制:1000ms 内存限制:65536kB 描述 将一个数组中的值按逆序重新存放. 例如,原来的顺 ...