BZOJ2125 最短路 【仙人掌最短路】
题目
给一个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 最短路 【仙人掌最短路】的更多相关文章
- BZOJ.2125.最短路(仙人掌 最短路Dijkstra)
题目链接 多次询问求仙人掌上两点间的最短路径. 如果是在树上,那么求LCA就可以了. 先做着,看看能不能把它弄成树. 把仙人掌看作一个图(实际上就是),求一遍根节点到每个点的最短路dis[i]. 对于 ...
- poj 3463 Sightseeing( 最短路与次短路)
http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS Memory Limit: 65536K Total Submissio ...
- 最短路和次短路问题,dijkstra算法
/* *题目大意: *在一个有向图中,求从s到t两个点之间的最短路和比最短路长1的次短路的条数之和; * *算法思想: *用A*求第K短路,目测会超时,直接在dijkstra算法上求次短路; ...
- UESTC30-最短路-Floyd最短路、spfa+链式前向星建图
最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同 ...
- POJ---3463 Sightseeing 记录最短路和次短路的条数
Sightseeing Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9247 Accepted: 3242 Descr ...
- hdu1688(dijkstra求最短路和次短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688 题意:第k短路,这里要求的是第1短路(即最短路),第2短路(即次短路),以及路径条数,最后如果最 ...
- CF 672C 两个人捡瓶子 最短路与次短路思想
C. Recycling Bottles time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- POJ 3463 Sightseeing 【最短路与次短路】
题目 Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the ...
- POJ - 3463 Sightseeing 最短路计数+次短路计数
F - Sightseeing 传送门: POJ - 3463 分析 一句话题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数. ...
随机推荐
- 爬虫学习(十二)——bs4实践案例
实践项目————诗词名句网<三国演义>小说爬取 import osimport reimport timeimport urllib.requestimport urllib.parsef ...
- Servlet学习笔记02——什么是http协议?
1.http协议 (了解) (1)什么是http协议? 是一种网络应用层协议,规定了浏览器与web服务器之间 如何通信以及相应的数据包的结构. 注: a.tcp/ip: 网络层协议,可以保证数据可靠的 ...
- Linux nohup 关闭终端的时候,程序依然能在后台运行( linux重定向及nohup不输出的方法)
先说一下linux重定向: 0.1和2分别表示标准输入.标准输出和标准错误信息输出,可以用来指定需要重定向的标准输入或输出.在一般使用时,默认的是标准输出,既1.当我们需要特殊用途时,可以使用其他标号 ...
- Android和IOS网页不一致汇总
1.input type=text 内容输入框的不一致,ios会默认给输入框添加自己的样式,导致在横向的输入框长度精准控制的时候,ios的输入框一般都比android上要长一点,还有内部阴影 解决此问 ...
- request中的那些方法到底是干什么的?
最近做Java Web项目,在.jsp页面和servlet之间request和response还是有些混淆,查阅了一些资料,总结如下,方便以后使用: 首先,servlet接口是最基本的,提供的五个方法 ...
- table选项卡
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- ADSL_自动拨号源码(Delphi),已经测试通过
下载地址: http://files.cnblogs.com/lwm8246/ADSL_%E8%87%AA%E5%8A%A8%E6%8B%A8%E5%8F%B7.rar
- zookeeper的搭建方法
1.创建三台虚拟机分别在虚拟机上安装Ubuntu16.04Server版的系统. 2.首先选择配置好第一台虚拟机,使用命令vim /etc/hosts对该文件进行修改 3.将zookeeper-3.4 ...
- Django自带后台管理配置
Django自带后台管理的配置 创建项目和应用 修改配置文件 数据库配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql' ...
- 使用泛型类简化ibatis系统架构
jdk1.5的推出为我们带来了枚举.泛型.foreach循环.同步工具包等等好东西.其中,泛型的使用为我们的代码开发提供了很大的简便,简化了我们的代码. 1.设计思路 1)GenericDao泛型类提 ...