题目

给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。

输入格式

输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一条无向边v-u,长度为w 最后Q行,每行两个整数v,u表示一组询问

输出格式

输出Q行,每行一个整数表示询问的答案

输入样例

9 10 2

1 2 1

1 4 1

3 4 1

2 3 1

3 7 1

7 8 2

7 9 2

1 5 3

1 6 4

5 6 1

1 9

5 7

输出样例

5

6

提示

对于100%的数据,N<=10000,Q<=10000

题解

仙人掌的题目,都与树上的方法相联系,再考虑环的影响

首先如果在树上,我们设d[u]表示u到根的距离,两点u,v的距离dis=d[u]+d[v]−2∗d[lca]

现在加上几个环,我们先跑一遍dfs找出所有的环以及算出d[],然后重构树,将环上的点全部连到该环最高点上,距离为环上到最高点的最短路

这样子构建出来的树,我们可以用倍增套用树的方法求解

如果求解时两点倍增时算得的最后祖先属于同一个环,那么就考虑环的贡献

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k; k = ed[k].nxt)
using namespace std;
const int maxn = 10005,maxm = 100005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
} int N,M,Q,h[maxn],ne = 2;
struct EDGE{int to,nxt,w;}ed[maxm];
inline void build(int u,int v,int w){
ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],w}; h[v] = ne++;
} int h2[maxn];
struct E{int to,nxt;}e[2 * maxn];
inline void add(int u,int v){e[ne] = (E){v,h2[u]}; h2[u] = ne++;} int dfn[maxn],low[maxn],d[maxn],dep[maxn],cnt = 0;
int fa[maxn][20],dis[maxn][20];
int cir[maxn],siz[maxn];
void getcir(int rt,int k){
int to = ed[k].to,len = d[to] - d[rt] + ed[k].w;
siz[++siz[0]] = len;
for (int i = to; i != rt; i = fa[i][0]){
add(rt,i);
dis[i][0] = min(d[i] - d[rt],len - d[i] + d[rt]);
cir[i] = siz[0];
}
}
void dfs(int u){
dfn[u] = low[u] = ++cnt; int to;
Redge(u) if ((to = ed[k].to) != fa[u][0]){
if (!dfn[to]){
fa[to][0] = u;
d[to] = d[u] + ed[k].w;
dfs(to);
low[u] = min(low[u],low[to]);
}else low[u] = min(low[u],dfn[to]);
if (dfn[u] < low[to]) add(u,to),dis[to][0] = ed[k].w;
}
Redge(u) if (fa[to = ed[k].to][0] != u && dfn[u] < dfn[to])
getcir(u,k);
}
void dfs2(int u){
REP(i,15){
fa[u][i] = fa[fa[u][i - 1]][i - 1];
dis[u][i] = dis[u][i - 1] + dis[fa[u][i - 1]][i - 1];
}
for (int k = h2[u],to; k; k = e[k].nxt){
fa[to = e[k].to][0] = u; dep[to] = dep[u] + 1;
dfs2(to);
}
}
int solve(int u,int v){
if (dep[u] < dep[v]) swap(u,v);
int ans = 0,D = dep[u] - dep[v];
for (int i = 0; (1 << i) <= D; i++)
if ((1 << i) & D) ans += dis[u][i],u = fa[u][i];
if (u == v) return ans;
for (int i = 15; i >= 0; i--)
if (fa[u][i] != fa[v][i]){
ans += dis[u][i] + dis[v][i];
u = fa[u][i]; v = fa[v][i];
}
if (cir[u] && cir[u] == cir[v])
ans += min(abs(d[u] - d[v]),siz[cir[u]] - abs(d[u] - d[v]));
else ans += dis[u][0] + dis[v][0];
return ans;
}
int main(){
N = RD(); M = RD(); Q = RD(); int a,b,w;
while (M--) a = RD(),b = RD(),w = RD(),build(a,b,w);
ne = 1;
dfs(1);
dep[1] = 1;
dfs2(1);
while (Q--){
a = RD(); b = RD();
printf("%d\n",solve(a,b));
}
return 0;
}

BZOJ2125 最短路 【仙人掌最短路】的更多相关文章

  1. BZOJ.2125.最短路(仙人掌 最短路Dijkstra)

    题目链接 多次询问求仙人掌上两点间的最短路径. 如果是在树上,那么求LCA就可以了. 先做着,看看能不能把它弄成树. 把仙人掌看作一个图(实际上就是),求一遍根节点到每个点的最短路dis[i]. 对于 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. POJ的层次感分类

    转载自:[http://blog.csdn.net/zzycsx/article/details/49103451] OJ上的一些水题(可用来练手和增加自信)  (poj3299,poj2159,po ...

  2. 远程桌面连接失败,提示CredSSP加密Oracel修正问题解决

    今天远程桌面的时候失败了,出现以下提示 于是上网找解决办法,经过测试,该方法是可行的. 首先,在控制台中输入regedit,打开注册表

  3. jsp <form>表单提交中如何在value属性中写表达式

    <input type="text" name="grop_id" value="<%=rs.getString(2)%>" ...

  4. hadoop-2.0.0-cdh4.1.2升级到hadoop-2.7.2

    升级前准备: 如果是 centos6.x的系统得升级glibc和pam包 在/etc/ld.so.conf 文件里添加 /usr/src/jdk1.6.0_23/jre/lib/amd64/serve ...

  5. python安装教程(面向对象的解释型计算机程序设计语言)

    inux下默认自带的.包括mac,是python2.x 但咱们玩的最新的  python3.x  怎么办呢centos下安装方法:  sudo yum install epel- sudo yum i ...

  6. mysql 存储过程的基本语法知识

    1 MySQL中的基本的存储过程 我将其分类为增删改查来逐一的分布来说 增加: //创建一个存储过程 $sql = " CREATE PROCEDURE TABLE_PR2() ---- 注 ...

  7. MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':ge

    数据库表里命名有这个字段,可怎么就是报错呢,大神的解释: 加上之后立马好用!!!

  8. 01,jupyter环境安装

    jupyter notebook环境安装 一.什么是Jupyter Notebook? 1. 简介 Jupyter Notebook是基于网页的用于交互计算的应用程序.其可被应用于全过程计算:开发.文 ...

  9. linux下解压命令大全[转]

    本文是复制大神的博文, 供自己参考. 原文出处:http://www.cnblogs.com/eoiioe/archive/2008/09/20/1294681.html .tar 解包:tar xv ...

  10. WIN8、WIN7访问Windows Server 2003服务器的数据库速度很慢、远程速度很慢的解决方法

    原因是微软在WIN7开始上加入了网络速度限制.在控制台执行以下命令即可解决: netsh interface tcp set global autotuninglevel=disabled