博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P5236-[模板]静态仙人掌【tarjan,LCA】
阅读量:2022 次
发布时间:2019-04-28

本文共 2074 字,大约阅读时间需要 6 分钟。

正题

题目链接:


题目大意

给一个边仙人掌(一条边至多在一个环中),每次询问两点之间的距离


解题思路

我们对于每个环新建方点,然后方点连向所有环上的点,然后计算一下每一条的边权

需要注意的是,如果两个询问点的 L C A LCA LCA是一个方点,那么需要特判


c o d e code code

#include
#include
#include
using namespace std;const int N=3e4+10,K=18;struct node{
int to,next,w;}a[N*2],e[N*2];int n,m,q,tot,num,cnt;int f[N][K],s[N],val[N],dep[N],dis[N];int ls[N],rs[N],dfn[N],low[N];void addl(int x,int y,int w){
a[++tot].to=y; a[tot].next=ls[x]; a[tot].w=w; ls[x]=tot;}void adde(int x,int y,int w){
e[++tot].to=y; e[tot].next=rs[x]; e[tot].w=w; rs[x]=tot;}void circle(int x,int y,int w){
num++;int now=y,sum=w; while(now!=f[x][0]){
s[now]=sum; sum+=val[now]; now=f[now][0]; } sum=s[num]=s[x]; s[x]=0;now=y; int Dis; while(now!=f[x][0]){
Dis=min(s[now],sum-s[now]); adde(num,now,Dis); adde(now,num,Dis); now=f[now][0]; } return;}void tarjan(int x){
dfn[x]=low[x]=++cnt; int flag=0; for(int i=ls[x];i;i=a[i].next){
int y=a[i].to; if(y==f[x][0])continue; if(!dfn[y]){
f[y][0]=x; val[y]=a[i].w;tarjan(y); low[x]=min(low[x],low[y]); } else low[x]=min(low[x],dfn[y]); if(low[y]<=dfn[x])continue; adde(x,y,a[i].w);adde(y,x,a[i].w); } for(int i=ls[x];i;i=a[i].next){
int y=a[i].to; if(x==f[y][0]||dfn[x]>=dfn[y])continue; circle(x,y,a[i].w); } return;}void dfs(int x,int fa){
for(int i=rs[x];i;i=e[i].next){
int y=e[i].to; if(y==fa)continue; dep[y]=dep[x]+1; dis[y]=dis[x]+e[i].w; f[y][0]=x;dfs(y,x); } return;}int Get_dis(int x,int y){
int u=x,v=y; if(dep[x]>dep[y])swap(x,y); for(int i=K-1;i>=0;i--) if(dep[f[y][i]]>=dep[x]) y=f[y][i]; int lca; if(x!=y){
for(int i=K-1;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; lca=f[x][0]; } else lca=x; if(lca<=n)return dis[u]+dis[v]-dis[lca]*2; else {
int ans=dis[u]-dis[x]+dis[v]-dis[y]; return ans+min(s[lca]-abs(s[x]-s[y]),abs(s[x]-s[y])); }}int main(){
scanf("%d%d%d",&n,&m,&q); num=n; for(int i=1;i<=m;i++){
int x,y,w; scanf("%d%d%d",&x,&y,&w); addl(x,y,w);addl(y,x,w); } tot=0;tarjan(1); dep[1]=1;dfs(1,0); for(int i=1;i

转载地址:http://zcwaf.baihongyu.com/

你可能感兴趣的文章
CSP考试 2015年9月第1题 数列分段 C语言实现
查看>>
CSP考试 2015年12月第1题 数位之和 C语言实现
查看>>
CSP考试 2016年4月第1题 折点计数 C语言实现
查看>>
CSP考试 2016年9月第1题 最大波动 C语言实现
查看>>
新手玩转GitHub
查看>>
【zookeeper】zookeeper的常用配置
查看>>
mysql实现for循环
查看>>
【linux is not unix】常用命令整理
查看>>
jvm参数
查看>>
【maven实战】第一遍总结
查看>>
服务器磁盘空间满后,导致构建项目报错。
查看>>
java如何对list进行分页查询---list分页查询工具类
查看>>
mac 版本charles安装报错-Charles cannot configure your proxy settings while it is on a read-only volume.
查看>>
Cannot construct instance of `com.*` (although at least one Creator exists): cannot deserializ
查看>>
Failed to start LSB: Bring up/down networking 终极解决方法
查看>>
docker x509: certificate has expired or is not yet valid
查看>>
springboot( 2.0.6.RELEASE)集成logback日志
查看>>
Mybatis Generator 生成的mapper只有insert方法
查看>>
Error creating bean with name ‘xmlModelPlugin‘: Lookup method resolution failed
查看>>
springboot动态调用实现类
查看>>