题目链接

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

如果是在树上,那么求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. Java与groovy混编 —— 一种兼顾接口清晰和实现敏捷的开发方式

    有大量平均水平左右的"工人"可被选择.参与进来 -- 这意味着好招人 有成熟的.大量的程序库可供选择 -- 这意味着大多数项目都是既有程序库的拼装,标准化程度高而定制化场景少 开发 ...

  2. CS53 C 单调栈

    给出一个目标序列,初始序列为0,你有一种操作方式可以将某段值相同的区间全部加上一定的值,问得到目标序列的最小次数. 开始没注意要求值相同,想都不想就暴力了,后来发现对于每个峰,只要找每个相对峰顶的阶数 ...

  3. JAVA io 包小结

    IO 无非读写 I --> Reader  O--> Writer 为了方便字符 或者 文本文件的 操作创造出了 字符流 尤其是 缓冲字符输入输出流(BufferedReader,Buff ...

  4. Brief History of Machine Learning

    Brief History of Machine Learning My subjective ML timeline Since the initial standpoint of science, ...

  5. 项目引入非配置的文件,打成war包后测试报错的可能原因

    写在前边 这阵子有点忙,开发一个微服务项目中读取配置文件的时候在本地测试是可以的,但是一到测试环境就报错,经查看发现是因为发布的时候是用的war包,使用java -jar xxx.war启动的,所以用 ...

  6. Oracle 修改用户名

    1.开始- 运行 - 输入“CMD” 确定 2.在弹出来的窗口中,输入:SQLPLUS / AS SYSDBA  回车 3.然后,用命令修改:alter user 用户名 identified by ...

  7. 洛谷 P3320: bzoj 3991: LOJ 2182: [SDOI2015]寻宝游戏

    题目传送门:LOJ #2182. 题意简述: 一棵 \(n\) 个节点的树,边有边权. 每个点可能是关键点,每次操作改变一个点是否是关键点. 求所有关键点形成的极小联通子树的边权和的两倍. 题解: 有 ...

  8. 学习mysql replication

  9. HttpClient使用之下载远程服务器中的文件(注意目录遍历漏洞)

    参考文献: http://bbs.csdn.net/topics/390952011 http://blog.csdn.net/ljj_9/article/details/53306468 1.下载地 ...

  10. elasticsearch安装servicewrapper插件

    1)下载elasticsearch-servicewrappergit clone https://github.com/elasticsearch/elasticsearch-servicewrap ...