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,那么在加上次短路的条数. ...
随机推荐
- ORM初级实战简单的数据库交互
setting.py中: """ Django settings for untitled3 project. Generated by 'django-admin st ...
- linux下csv导出文件中文乱码问题
近日在服务器端通过导出csv文件,将数据从linux服务器端保存到windows桌面端,以便用户可以通过excel打开使用数据. 但是在使用excel打开csv文件时,出现了中文乱码的情况,但是使用记 ...
- Python面向对象--高级(二)
## 使用__slots__限制类的属性 - 之前说到,可以通过在类外部实例或者类名任意定义实例属性或者类属性或者方法 class Person(object): pass Person.name = ...
- PHP设计者---composer
Composer 是 PHP5以上 的一个依赖管理工具.它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们.Composer 不是一个包管理器.是的,它涉及 "packages&q ...
- 微信小程序相关
https://www.cnblogs.com/shenzikun1314/p/7805168.html
- html5中的progress兼容ie,制作进度条样式
html5新增的progress标签用处很大,它可以制作进度条,不用像以前那样用css来制作进度条! 一.progress使用方法 progress标签很好使用,他有两个属性,value和max,va ...
- HAN模型理解1
HAN 模型 最开始看这个模型是看的这个解释: RNN+Attention(HAN) 文本分类 阅读笔记 - 今天做作业没的文章 - 知乎 https://zhuanlan.zhihu.com/p/4 ...
- POJ:3061-Subsequence(尺取法模板详解)
Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18795 Accepted: 8043 Descript ...
- [USACO12JAN]视频游戏的连击Video Game Combos(AC自动机+DP)
Description 贝西正在打格斗游戏.游戏里只有三个按键,分别是“A”.“B”和“C”.游戏中有 N 种连击 模式,第 i 种连击模式以字符串 Si 表示,只要贝西的按键中出现了这个字符串,就算 ...
- 笔记-scrapy-辅助功能
笔记-scrapy-辅助功能 1. scrapy爬虫管理 爬虫主体写完了,要部署运行,还有一些工程性问题: 限频 爬取深度限制 按条件停止,例如爬取次数,错误次数: 资源使用限制,例如内存限 ...