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 ...
随机推荐
- 数据库——SQL中EXISTS怎么用1(转)
EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False 方法/步骤 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返 ...
- JavaScrip——DOM操作(属性操作)
Attribute a.setAttribute("属性名","属性值")——设置属性 a.getSttribute("属性名")——获取属 ...
- linux后台运行jar程序
Linux 运行jar包命令如下: 方式一:java -jar XXX.jar特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出那如何让窗口不锁定? 方式二java ...
- TCP协议的问题
Server端接收到Client端信息后不会返回给Client端 // TCPEchoServer.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h&quo ...
- json拼接转义符
//转义符替 function escapeReplace(Str) { var newStrJson = Str.replace(/\%/g, "%25"); newStrJso ...
- ADT Android Development Tools
ADT(Android Development Tools)在Eclipse编译IDE环境中,需安装ADT(Android Developer Tools)Plug-in,这是Android在Ecli ...
- 利用Spring AOP和自定义注解实现日志功能
Spring AOP的主要功能相信大家都知道,日志记录.权限校验等等. 用法就是定义一个切入点(Pointcut),定义一个通知(Advice),然后设置通知在该切入点上执行的方式(前置.后置.环绕等 ...
- jQuery的Ajax操作小结——$.ajax和$.getJSON等用法小结
一.$.ajax用法与举例 jQuery.ajax(url,[settings]) ——返回值:XMLHttpRequest 通过 HTTP 请求加载远程数据,这个是jQuery 的底层 AJ ...
- 监视在input框中按下回车(enter) js实现
function getKey(event) { if (event.keyCode == 13) { alert("我是回车键"); } } <input type=&qu ...
- rdesktop连接远程windows
$ info rdesktop //看一下帮助信息吧$rdesktop 192.168.1.1 //打开了一个8位色彩的,$rdesktop -a 16 192.168.1.1 //这个是16位色 ...