题目链接

多次询问求仙人掌上两点间的最短路径。

如果是在树上,那么求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)的更多相关文章

  1. 最短路和次短路问题,dijkstra算法

    /*  *题目大意:  *在一个有向图中,求从s到t两个点之间的最短路和比最短路长1的次短路的条数之和;  *  *算法思想:  *用A*求第K短路,目测会超时,直接在dijkstra算法上求次短路; ...

  2. hdu1688(dijkstra求最短路和次短路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688 题意:第k短路,这里要求的是第1短路(即最短路),第2短路(即次短路),以及路径条数,最后如果最 ...

  3. bzoj 1726: [Usaco2006 Nov]Roadblocks第二短路【dijskstra】

    严格次短路模板,用两个数组分别维护最短路和次短路,用dijskstra,每次更新的时候先更新最短路再更新次短路 写了spfa版的不知道为啥不对-- #include<iostream> # ...

  4. poj 3463 Sightseeing( 最短路与次短路)

    http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissio ...

  5. POJ---3463 Sightseeing 记录最短路和次短路的条数

    Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9247   Accepted: 3242 Descr ...

  6. POJ 3463 Sightseeing 【最短路与次短路】

    题目 Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the ...

  7. UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

    最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同 ...

  8. CF 672C 两个人捡瓶子 最短路与次短路思想

    C. Recycling Bottles time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. POJ - 3463 Sightseeing 最短路计数+次短路计数

    F - Sightseeing 传送门: POJ - 3463 分析 一句话题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数. ...

随机推荐

  1. SQL记录-PLSQL-EXIT/CONTINUE/GOTO

    PL/SQL EXIT语句   在PL/SQL编程语言中,EXIT语句有以下两种用法: 当循环中遇到EXIT语句循环立即终止,程序控制继续下一个循环语句后面. 如果使用嵌套循环(即一个循环内的另一个循 ...

  2. MingW-v4.8.0+EDE-v13.04 配置使用C语言图形库

    From: http://www.cnblogs.com/killerlegend/p/3946768.html Author:KillerLegend Date:2014.8.30 MingW的配置 ...

  3. bzoj千题计划181:bzoj1878: [SDOI2009]HH的项链

    http://www.lydsy.com/JudgeOnline/problem.php?id=1878 之前用莫队做的,现在用树状数组 把每种数的第一个出现位置在树状数组中+1 nxt[i] 记录i ...

  4. nodejs安装zmq出错

    想用zmq来做进程间通信,在Windows下.Centos下安装成功.记录如下: 一.Windows安装zmq 直接 npm install zmq  成功就成功. 不成功的话估计是报"未能 ...

  5. Nodejs stream模块-翻译

    花了两天时间尝试按照自己的话翻译了一下stream模块,以下内容皆翻译于:https://nodejs.org/api/stream.html. 目录 1  Stream(流)     1.1     ...

  6. Django Book学习笔记(下)

    Django的Session框架 对于Django加密,大致使用这样的格式: hashtype$salt$hash 原因? 一次哈希是一次单向的加密过程,你能容易地计算出一个给定值的哈希码,但是几乎不 ...

  7. 20155203 2016-2017-2 《Java程序设计》第7周学习总结

    20155203 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 1.Lambda表达式.(使用interface函数接口) 2.Lambda的方法参考Met ...

  8. shell 流程结构

    if 判断语句 if [ $a == $b ] then echo "等于" else echo "不等于" fi case分支选择 case $xs in ) ...

  9. gitminer

    https://github.com/UnkL4b/GitMiner + Autor: UnK + Blog: https://unkl4b.github.io + Github: https://g ...

  10. linux批量关闭进程

    ps aux | grep gunicorn_api | awk '{print $2}' | xargs kill -9 gunicorn 换成你的关键字即可.