JZOJ.5287【NOIP2017模拟8.16】最短路
Description
Input
Output
Sample Input
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
Sample Output
5
6
Data Constraint
容易发现这是一张仙人掌图(每条边最多属于一个环的无向连通图)
仙人掌图求最短路的常用处理方法是将它变成一棵树,原图里为环的点更改为该环上的点都指向该环的某个点A,然后边长就是该点到点A的最短路径。
再预处理每个点到顶点的距离dis。
然后对于询问的两个点u,v,如果u,v的LCA不在环上,那么距离就直接是dis[u]+dis[v]-2*dis[LCA(u,v)].
如果在环上,那么对于它们进入环的点Cu,Cv则有两种走法,一种是从Cu顺时针走向Cv,另一种是从Cu逆时针走向Cv,两者取最小再加上dis[u]+dis[v]-dis[Cu]-dis[Cv]就可以了。
至于求环,我们可以运用Tarjan的思想。求LCA用倍增就可以了。值得注意的是,这里可以一个点在两个环里。
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#define N 400005
using namespace std;
struct data{
int next,to,power;
}l1[N],l2[N];
int n,m,q,f1[N/],f2[N/],dfn[N/],num1,num2,head1[N],head2[N],zhan[N],top,up[N][],t,deep[N],dis[N/],belong[N],f[N/],visit[N/],host[N/],cnt;
int read(){
int x=,w=;
char c=;
for (c=getchar();c<''||c>'';c=getchar()) {if (c=='-') w=-;}
for (;c>=''&&c<='';c=getchar()) x=(x<<)+(x<<)+c-'';
return x*w;
}
void write(long long x){
if (!x) putchar('');else{
char s[];
int i,j=;
for (;x>;x/=) s[j++]=x%;
for (i=j-;i>=;i--) putchar(s[i]+);
}
putchar('\n');
}
void add1(int u,int v,int w){
num1++;
l1[num1].next=head1[u];
l1[num1].to=v;
l1[num1].power=w;
head1[u]=num1;
num1++;
l1[num1].next=head1[v];
l1[num1].to=u;
l1[num1].power=w;
head1[v]=num1;
}
void add2(int u,int v,int w){
num2++;
l2[num2].next=head2[u];
l2[num2].to=v;
l2[num2].power=w;
head2[u]=num2;
num2++;
l2[num2].next=head2[v];
l2[num2].to=u;
l2[num2].power=w;
head2[v]=num2;
}
void DFS(int x){
dfn[x]=++t;
for (int v=,i=head1[x];i;i=l1[i].next){
v=l1[i].to;
if ((v!=f[x])&&(!dfn[v])){
f[v]=x;
zhan[++top]=i;
DFS(v);
}
else if ((v!=f[x])&&(dfn[v]<dfn[x])){
long long sum=l1[i].power;
int p=top;
while ((l1[zhan[p]].to!=v)&&(p)){
f1[l1[zhan[p]].to]=sum;
sum+=l1[zhan[p]].power;
p--;
}
cnt++;
sum=l1[zhan[p+]].power;
for (int j=p+;j<=top;++j){
f2[l1[zhan[j]].to]=sum;
host[l1[zhan[j]].to]=v;
belong[l1[zhan[j]].to]=cnt;
add2(v,l1[zhan[j]].to,min(f1[l1[zhan[j]].to],f2[l1[zhan[j]].to]));
sum+=l1[zhan[j+]].power;
}
}
}
top--;
}
void build(int x){
visit[x]=;
for (int v=,i=head1[x];i;i=l1[i].next){
v=l1[i].to;
if ((!visit[v])&&(v!=f[x])){
if (((belong[x]!=belong[v])||((!belong[x])&&(!belong[v])))&&(host[x]!=v)&&(host[v]!=x))
add2(x,v,l1[i].power);
build(v);
}
}
}
void pre(int x){
deep[x]=deep[f[x]]+;
up[x][]=f[x];
for (int i=;i<=;++i)
up[x][i]=up[up[x][i-]][i-];
for (int v=,i=head2[x];i;i=l2[i].next){
v=l2[i].to;
if ((!deep[v])&&(v!=f[x])) {
f[v]=x;
dis[v]=dis[x]+l2[i].power;
pre(v);
}
}
}
int lca(int u,int v,int www){
int a=u,b=v;
if (deep[u]<deep[v]) swap(u,v);
for (int i=;i>=;--i)
if (deep[v]<=deep[up[u][i]])
u=up[u][i];
if (u==v) return (dis[a]-dis[u]+dis[b]-dis[v]);
for (int i=;i>=;--i)
if (up[v][i]!=up[u][i]){
v=up[v][i];
u =up[u][i];
}
if ((u!=v)&&(belong[u])&&(belong[u]==belong[v])) return (dis[a]-dis[u]+dis[b]-dis[v]+min(min(f1[u]+f2[v],f1[v]+f2[u]),min(abs(f1[u]-f1[v]),abs(f2[u]-f2[v]))));
else return (dis[a]-dis[up[u][]]+dis[b]-dis[up[v][]]);
}
int main(){
n=read(),m=read(),q=read();
t=,num1=,num2=,top=,cnt=;
for (int v=,u=,w=,i=;i<=m;++i){
u=read(),v=read(),w=read();
add1(u,v,w);
}
deep[]=-;
f[]=;
dis[]=;
DFS();
build();
f[]=;
pre();
for (int u=,v=,i=;i<=q;++i){
u=read(),v=read();
write(lca(u,v,i));
}
return ;
}
神奇的代码
拖欠了好几天的题终于A了QAQ
JZOJ.5287【NOIP2017模拟8.16】最短路的更多相关文章
- JZOJ.5286【NOIP2017模拟8.16】花花的森林
Description
- JZOJ.5285【NOIP2017模拟8.16】排序
Description
- [jzoj 5343] [NOIP2017模拟9.3A组] 健美猫 解题报告 (差分)
题目链接: http://172.16.0.132/senior/#main/show/5343 题目: 题解: 记旋转i次之后的答案为$ans_i$,分别考虑每个元素对ans数组的贡献 若$s_i& ...
- [JZOJ 5908] [NOIP2018模拟10.16] 开荒(kaihuang)解题报告 (树状数组+思维)
题目链接: https://jzoj.net/senior/#contest/show/2529/1 题目: 题目背景:尊者神高达作为一个萌新,在升级路上死亡无数次后被一只大黄叽带回了师门.他加入师门 ...
- [JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)
题目链接: https://jzoj.net/senior/#contest/show/2529/2 题目: 题目背景:尊者神高达很穷,所以他需要跑商来赚钱题目描述:基三的地图可以看做 n 个城市,m ...
- JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林 (Standard IO)
5286. [NOIP2017提高A组模拟8.16]花花的森林 (Standard IO) Time Limits: 1000 ms Memory Limits: 131072 KB Descript ...
- JZOJ 5236. 【NOIP2017模拟8.7A组】利普希茨
5236. [NOIP2017模拟8.7A组]利普希茨 (File IO): input:lipschitz.in output:lipschitz.out Time Limits: 1000 ms ...
- JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠
JZOJ [NOIP2017提高A组模拟9.14]捕老鼠 题目 Description 为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里的仓库灭灭鼠.于是,猫被农夫约派去捕 ...
- JZOJ 5246. 【NOIP2017模拟8.8A组】Trip(trip)
5246. [NOIP2017模拟8.8A组]Trip(trip) (File IO): input:trip.in output:trip.out Time Limits: 1500 ms Memo ...
随机推荐
- [LintCode]转换字符串到整数
问题描述: 实现atoi这个函数,将一个字符串转换为整数.如果没有合法的整数,返回0.如果整数超出了32位整数的范围,返回INT_MAX(2147483647)如果是正整数,或者INT_MIN(-21 ...
- 实现整数转化为字符串函数itoa()函数
函数原型: char *itoa( int value, char *string,int radix);原型说明:value:欲转换的数据.string:目标字符串的地址.radix:转换后的进制数 ...
- r语言 函数
R语言实际上是函数的集合,用户可以使用base,stats等包中的基本函数,也可以自己编写函数完成一定的功能.但是初学者往往认为编写R函数十分困难,或者难以理解.这里对如何编写R函数进行简要的介绍. ...
- 6款强大的 jQuery 网页布局创建及优化插件
本文将为您介绍6款功能强大的jQuery插件,它们能够帮助您方便快捷地创建复杂的网络布局并进行优化. 1.UI.Layout 该插件可以创建任何你想要的UI形式:包括从简单的标题或侧边栏,到一个包含工 ...
- [svn] 在线安装
SVN地址:http://subclipse.tigris.org/update_1.6.x/
- Linux之查看文件大小和数目
1.查看当前文件大小du -sh ./ du [-abcDhHklmsSx] [-L <符号连接>][-X <文件>][--block-size][--exclude=< ...
- spring复习 -day1:Spring简介 、 Spring容器 、 Spring IOC
Spring创建对象方法 创建对象过程: 第一步:添加SpringIOC环境 (1)在WebRoot/WEB-INT/lib文件夹下,引入SpringIOC配置环境的jar包 如图: (2)在sr ...
- 第二百八十三节,MySQL数据库-MySQL存储过程
MySQL数据库-MySQL存储过程 MySQL存储过程,也就是有点像MySQL函数,但是他与MySQL函数是有区别的,后面会讲到函数,所以注意区分 注意:函数与存储过程的区别 存储过程是:CREAT ...
- PhoneGap开发不可或缺的五件装备
PhoneGap是一种介于WebApp和NativeApp之间的解决方案,它为每种移动客户端提供一个Native的壳,这种壳里边包着一个Web应 用.借助于壳,Web应用可以被安装,可以被发布到各大市 ...
- Ubuntu adb devices : no permissions 解决方法
ntun下USB连接Android手机后,使用adb devices 出现如下: List of devices attached ???????????? no permissions 同时在DDM ...