BZOJ.2125.最短路(仙人掌 最短路Dijkstra)
多次询问求仙人掌上两点间的最短路径。
如果是在树上,那么求LCA就可以了。
先做着,看看能不能把它弄成树。
把仙人掌看作一个图(实际上就是),求一遍根节点到每个点的最短路dis[i]。
对于u,v,若w=LCA(u,v)不在环上(u,v不同在一个环),那么dis(u,v)可以像在树上一样直接求得。
若w=u||w=v,(且w不是环内的一个点),dis(u,v)=dis[u/v]-dis[w]。
如果w在环上,那么设x,y为u,v往上距离最近的环上的离u,v最近的两个点,那么dis(u,v)=dis[u]-dis[x]+dis[v]-dis[y]+(x,y在环上的最短距离)。
设cdis[i]为按DFS序得到的根节点到i的距离,len[i]为环i的长,x,y在环上的最短距离就是min(abs(cdis[x]-cdis[y]),len[bel]-abs(cdis[x]-cdis[y]))。
怎么把它弄成一棵树 求LCA?
所有在一个环上的点以这个环深度最小的点作为父节点,由父节点向子节点连边就行了。之前缩一下点。
求仙人掌上单源最短路可以O(n)DP
太弱不会。。
这代码总感觉有问题,果然。。这就卡掉了
8 9 1
1 2 10
2 3 10
4 7 5
4 6 10
4 5 10
4 3 10
5 1 10
6 7 16
7 8 10
7 8
重写吧。。在这儿,正好练练圆方树。
//6492kb 376ms
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define mp std::make_pair
#define pr std::pair<int,int>
const int N=1e4+5,M=2e5+5;
int n,m,Q,Enum,H[N],nxt[M<<1],to[M<<1],val[M<<1],dis[N],cnt,bel[N],len[N],cdis[N],dep[N],fa[N][16];
std::priority_queue<pr> q;
bool vis[N],vis2[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v,int w){
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, val[Enum]=w;
}
void Dijkstra()
{
memset(dis,0x3f,sizeof dis);
dis[1]=0, q.push(mp(0,1));
while(!q.empty())
{
int x=q.top().second; q.pop();
if(vis2[x]) continue;
vis2[x]=1;
for(int i=H[x]; i; i=nxt[i])
if(dis[to[i]]>dis[x]+val[i])
dis[to[i]]=dis[x]+val[i], q.push(mp(-dis[to[i]],to[i]));
}
}
void DFS(int x)
{
vis[x]=1;
for(int v,i=H[x]; i; i=nxt[i])
if(to[i]!=fa[x][0]&&!bel[to[i]])
if(!vis[v=to[i]]) fa[v][0]=x,cdis[v]=cdis[x]+val[i],dep[v]=dep[x]+1,DFS(v);
else{//find a circle v
len[++cnt]=cdis[x]-cdis[v]+val[i];
for(int j=x,pre; j!=v; j=pre)
bel[j]=cnt, pre=fa[j][0], fa[j][0]=v;
//不给bel[v]赋值,因为v可能作为多个环的交点。
}
}
void Init_LCA()
{
for(int x=2; x<=n; ++x)
// for(int i=1; i<16&&dep[x]>=(1<<i); ++i)
for(int i=1; i<16; ++i)
fa[x][i]=fa[fa[x][i-1]][i-1];
}
void Query_LCA(int &u,int &v)
{
if(dep[u]<dep[v]) std::swap(u,v);
for(int i=15; ~i; --i)
if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];//这样dep[1]=1!
if(u==v) return;
for(int i=15; ~i; --i)
if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
// u=fa[u][0], v=fa[v][0];
}
void DFS_for_Deep(int x){
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa[x][0]) dep[to[i]]=dep[x]+1, DFS_for_Deep(to[i]);
}
int main()
{
n=read(),m=read(),Q=read();
for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),AddEdge(u,v,read());
Dijkstra(), DFS(1);
Enum=0, memset(H,0,sizeof H);
for(int i=2; i<=n; ++i) AddEdge(fa[i][0],i,0);
dep[1]=1, DFS_for_Deep(1)/*在新树上得到dep啊。。*/, Init_LCA();
int u,v,x,y,l;
while(Q--)
{
u=read(),v=read(),Query_LCA(x=u,y=v);//此时的x,y若在环上,则是最接近u,v的环上的点(再往上跳一步就是LCA,环深度最低的点)
if(x!=y && bel[x] && bel[x]==bel[y])//x!=y即u,v不是在一条链上 //注意判bel[x]!=0!
printf("%d\n",dis[u]+dis[v]-dis[x]-dis[y]+std::min(std::abs(cdis[x]-cdis[y]),len[bel[x]]-std::abs(cdis[x]-cdis[y])));
else if(x==y) printf("%d\n",dis[u]+dis[v]-(dis[x]<<1));
else printf("%d\n",dis[u]+dis[v]-(dis[fa[x][0]]<<1));//不在一个环上也直接更新。
}
return 0;
}
BZOJ.2125.最短路(仙人掌 最短路Dijkstra)的更多相关文章
- 最短路和次短路问题,dijkstra算法
/* *题目大意: *在一个有向图中,求从s到t两个点之间的最短路和比最短路长1的次短路的条数之和; * *算法思想: *用A*求第K短路,目测会超时,直接在dijkstra算法上求次短路; ...
- hdu1688(dijkstra求最短路和次短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688 题意:第k短路,这里要求的是第1短路(即最短路),第2短路(即次短路),以及路径条数,最后如果最 ...
- bzoj 1726: [Usaco2006 Nov]Roadblocks第二短路【dijskstra】
严格次短路模板,用两个数组分别维护最短路和次短路,用dijskstra,每次更新的时候先更新最短路再更新次短路 写了spfa版的不知道为啥不对-- #include<iostream> # ...
- poj 3463 Sightseeing( 最短路与次短路)
http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS Memory Limit: 65536K Total Submissio ...
- POJ---3463 Sightseeing 记录最短路和次短路的条数
Sightseeing Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9247 Accepted: 3242 Descr ...
- POJ 3463 Sightseeing 【最短路与次短路】
题目 Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the ...
- UESTC30-最短路-Floyd最短路、spfa+链式前向星建图
最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同 ...
- CF 672C 两个人捡瓶子 最短路与次短路思想
C. Recycling Bottles time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- POJ - 3463 Sightseeing 最短路计数+次短路计数
F - Sightseeing 传送门: POJ - 3463 分析 一句话题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数. ...
随机推荐
- [六字真言]5.咪.功力不足,学习前端JavaScript异常
A Guide to Proper Error Handling in JavaScript 这是关于JavaScript中异常处理的故事.如果你相信 墨菲定律 ,那么任何事情都可能出错,不,一定会出 ...
- HDU 3389 阶梯博弈变形
n堆石子,每次选取两堆a!=b,(a+b)%2=1 && a!=b && 3|a+b,不能操作者输 选石子堆为奇数的等价于选取步数为奇数的,观察发现 1 3 4 是无法 ...
- java学习第04天(语句、函数、数组)
(3)循环结构 格式: for(初始化表达式,循环条件表达式,循环后的操作变大时){ 执行语句,循环体: } 注: a. for循环里面的连个表达式运行的顺序,初始化表达式只读一次,判断循环条件,为真 ...
- 第5月第21天 bugly ios证书位置
1.bugly 一. 本地测试 补丁编写规则参见: JSPatch 将补丁文件main.js拖拽到工程内: 开启 BuglyConfig 中的热更新本地调试模式: BuglyConfig *confi ...
- linux 图形配置网络
命令:setup 打开网络等系统信息的图形配置 yyp复制 vi /etc/sysconfig/network-scripts/ifcfg-eth0 配置网络参数 重启网卡:/etc/init.d/n ...
- ApiCloud利用NVTabBar模块快速搭建起APP的框架
废话不说,直接上代码 模块地址:https://docs.apicloud.com/Client-API/Nav-Menu/NVTabBar 代码实例: <!doctype html> & ...
- crontab机会任务监控
<1>如何查看自己的计划任务是否成功的执行? 昨天crontab中的同步任务没有执行,不知道是什么原因没有执行,貌似任务hang住了,想查询一下crontab到底问题出在哪里,或者hang ...
- 兼容IE FF 获取鼠标位置
由于Firefox和IE等浏览器之间对js解释的方式不一样,firefox下面获取鼠标位置不能够直接使用clientX来获取.网上说的一般都是触发mousemove事件才行.我这里有两段代码,思路都一 ...
- window BIOS设置硬盘启动模式
bios如何设置硬盘启动模式?BIOSD硬盘模试主是要针对IDE接口的硬盘和SATA接口的硬盘来设置的.以前的主板只支持一种类型.现在的智能笔记本主板支持:IDE Mode.AHCI Mode.下 ...
- linux进程的一些日常处理
linux 下查看一个进程运行路径的方法 在linux下查看进程大家都会想到用 ps -ef|grep XXX 可是看到的不是全路径,怎么看全路径呢? 每个进程启动之后在 /proc下面有一个于pid ...