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,那么在加上次短路的条数. ...
随机推荐
- Redis五种数据结构(Windows Server)
1.Redis的五种数据结构 这里推荐大家在命名redis的key的时候最好的加上前缀,并且使用 :来分割前缀 ,这里在使用可视化工具查看的时候就比较好区分,比如我的的前缀是 Demo:test:(一 ...
- Myeclipse 工具优化 [内存一直增加, jsp,javascript 编辑很卡]
首先看这篇随笔 地址: Myeclipse/STS 首次在本地部署配置一个Spring MVC 项目 (十二) [http://www.cnblogs.com/editor/p/3915239.htm ...
- Spring Tool Suite 创建 SpringMVC+Maven 项目(一)!
使用Spring Tool Suite 创建 SpringMVC Web 项目,使用Maven来管理依赖! 首先对环境进行必要的配置 1. 配置必要的Java JDK版本! (菜单栏-窗口-首选项.) ...
- 20155305乔磊2016-2017-2《Java程序设计》第六周学习总结
20155305乔磊2016-2017-2<Java程序设计>第六周学习总结 教材学习内容总结 InputStream与OutputStream 串流设计 1.串流:Java将输入/输出抽 ...
- python之pip安装mysql-python失败
前言 由于公司使用的python版本是python2,并且连接mysql的包是mysql-python,但是mysql-python 使用pip安装报错,需要C++环境等依赖,于是使用wheel直接安 ...
- 『实践』Yalmip+Ipopt+Cplex使用手册
Yalmip+Ipopt+Cplex使用手册 1.软件版本 Cplex 12.6.2,Matlab R2014a,Ipopt 3.12.9,Yalmip 2.Cplex添加方法 官方下载地址: htt ...
- Redis Scan命令
原地址:https://www.cnblogs.com/tekkaman/p/4887293.html [Redis Scan命令] SCAN cursor [MATCH pattern] [COUN ...
- sass和scss相关知识
参考地址:http://www.imooc.com/learn/311 什么是css预处理器? CSS 预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为 CSS 增加了一些编程的特性 ...
- SysV和BSD启动风格的比较
Slackware启动脚本与System V启动脚本的区别何在? Slackware 使用BSD风格的init脚本,而很多别的发行版使用System V风格的init脚本.SysV和BSD脚本都是能让 ...
- java 代理 agency
java并没有对其提供直接的支持,这是继承和组合的中庸之道,因为我们将一个成员对象置于所要构造的类中(组合),但与此同时我们在新类中暴露了该成员的所有方法(就像继承),使用代理时可以拥有更多的控制力, ...