传送门:Problem 3195

https://www.cnblogs.com/violet-acmer/p/9686774.html

题意:

  给一个无根树,有q个询问,每个询问3个点(a,b,c),问将这3个点连起来,距离最短是多少。

题解:

  我的思路:

    (1)分别求出Lca(a,b),Lca(a,c),Lca(b,c);

    (2)找到三个Lca( )中深度最深的那个节点(此处假设Lca(a,b)深度最深),设变量 res = dist[a]+dist[b]-2*dist[Lca(a,b)];

    (3)求出Lca(a,b)与c的最近公共祖先,res += dist[c]+dist[Lca(a,b)]-2*dist[Lca(a,b,c)];

  参考大佬题解思路:

    分别求LCA(a,b),LCA(a,c),LCA(b,c),和对应的距离,然后3个距离相加再除以2就是这个询问的结果。

AC代码:

  晚上看了LCA的RMQ算法的一个题,改了一晚上,貌似理解了,太累了,明天再把这个代码的细节写一下.............

 #include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
#define pb push_back
#define ll long long
#define mem(a,b) (memset(a,b,sizeof a))
const int maxn=5e4+; struct Node
{
int to;
int weight;
Node(int to,int weight):to(to),weight(weight){}
};
vector<Node >edge[maxn];
int n,q;
int fa[][maxn];
int dist[maxn];
int depth[maxn];
void addEdge(int u,int v,int w)
{
edge[u].pb(Node(v,w));
edge[v].pb(Node(u,w));
}
void Init()
{
for(int i=;i < n;++i)
edge[i].clear();
}
void Dfs(int u,int f,int d,int l)
{
fa[][u]=f;
dist[u]=l;
depth[u]=d;
for(int i=;i < edge[u].size();++i)
{
int to=edge[u][i].to;
int w=edge[u][i].weight;
if(to != f)
Dfs(to,u,d+,l+w);
}
}
void Pretreat()
{
Dfs(,-,,);
for(int k=;k+ < ;++k)
for(int u=;u < n;++u)
if(fa[k][u] == -)
fa[k+][u]=-;
else
fa[k+][u]=fa[k][fa[k][u]];
}
int Lca(int u,int v)
{
if(depth[u] > depth[v])
swap(u,v);
int k;
for(k=;(<<k) <= depth[v];++k);
k--;
for(int i=k;i >= ;--i)
if((depth[v]-(<<i)) >= depth[u])
v=fa[i][v];
if(u == v)
return v;
for(int i=k;i >= ;--i)
if(fa[i][v] != - && fa[i][v] != fa[i][u])
{
v=fa[i][v];
u=fa[i][u];
}
return fa[][v];
}
int main()
{
bool flag=false;
while(~scanf("%d",&n))
{
Init();
if(flag)
printf("\n");
flag=true;
for(int i=;i < n;++i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
}
Pretreat();
scanf("%d",&q);
for(int i=;i <= q;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int res;
int lcaAB=Lca(a,b);
int lcaAC=Lca(a,c);
int lcaBC=Lca(b,c);
if(depth[lcaAB] > depth[min(lcaAC,lcaBC)])
{
res=dist[a]-dist[lcaAB]+dist[b]-dist[lcaAB];
res += dist[lcaAB]-dist[Lca(lcaAB,c)]+dist[c]-dist[Lca(lcaAB,c)];
}
else if(depth[lcaAC] > depth[min(lcaAB,lcaBC)])
{
res=dist[a]-dist[lcaAC]+dist[c]-dist[lcaAC];
res += dist[lcaAC]-dist[Lca(lcaAC,b)]+dist[b]-dist[Lca(lcaAC,b)];
}
else
{
res=dist[b]-dist[lcaBC]+dist[c]-dist[lcaBC];
res += dist[lcaBC]-dist[Lca(lcaBC,a)]+dist[a]-dist[Lca(lcaBC,a)];
}
printf("%d\n",res);
}
}
return ;
}

基于二分的LCA

zoj 3195(LCA加强版)的更多相关文章

  1. zoj 3195 Design the city LCA Tarjan

    题目链接 : ZOJ Problem Set - 3195 题目大意: 求三点之间的最短距离 思路: 有了两点之间的最短距离求法,不难得出: 对于三个点我们两两之间求最短距离 得到 d1 d2 d3 ...

  2. ZOJ 3195 Design the city LCA转RMQ

    题意:给定n个点,下面n-1行 u , v ,dis 表示一条无向边和边权值,这里给了一颗无向树 下面m表示m个询问,问 u v n 三点最短距离 典型的LCA转RMQ #include<std ...

  3. zoj 3195 Design the city lca倍增

    题目链接 给一棵树, m个询问, 每个询问给出3个点, 求这三个点之间的最短距离. 其实就是两两之间的最短距离加起来除2. 倍增的lca模板 #include <iostream> #in ...

  4. ZOJ 3195 Design the city (LCA 模板题)

    Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terribl ...

  5. zoj——3195 Design the city

    Design the city Time Limit: 1 Second      Memory Limit: 32768 KB Cerror is the mayor of city HangZho ...

  6. ZOJ 3195 Design the city 题解

    这个题目大意是: 有N个城市,编号为0~N-1,给定N-1条无向带权边,Q个询问,每个询问求三个城市连起来的最小权值. 多组数据 每组数据  1 < N < 50000  1 < Q ...

  7. zoj 3195

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3320 离线算法RE了.. #include<stdio.h> #i ...

  8. zoj 3649 lca与倍增dp

    参考:http://www.xuebuyuan.com/609502.html 先说题意: 给出一幅图,求最大生成树,并在这棵树上进行查询操作:给出两个结点编号x和y,求从x到y的路径上,由每个结点的 ...

  9. ZOJ - 3195 Design the city

    题目要对每次询问将一个树形图的三个点连接,输出最短距离. 利用tarjan离线算法,算出每次询问的任意两个点的最短公共祖先,并在dfs过程中求出离根的距离.把每次询问的三个点两两求出最短距离,这样最终 ...

随机推荐

  1. C. Oh Those Palindromes

    题意 给以一个字符串,让你重排列,使得回文子串的数目最多 分析 对于一个回文串,在其中加入一些字符并不会使回文子串的个数增加,所以对于相同的字符一起输出即可,我是直接排序 代码 #include< ...

  2. 第三周作业(三)---WordCounter

    需求是这样的.写出一个程序,模仿wc.exe,可以统计出文件的一些信息(比如字符数.单词数目等等) 对于这个程序,我仍然用我从大一学来的C语言写的. 第一步:打开文件 printf("请输入 ...

  3. Rop框架学习笔记

    1.  提供了开发服务平台的解决方案:比如应用认证.会话管理.安全控制.错误模型.版本管理.超时限制 2.  启动:RopServlet截获http请求 配置: <servlet> < ...

  4. Linux期末总结

    Linux内核学习总结 1.计算机是如何工作的? 存储程序计算机工作模型 X86汇编基础 汇编一个简单的C程序分析其汇编指令执行过程 2.操作系统是如何工作的? 三个法宝——存储程序计算机.函数调用堆 ...

  5. 《Linux内核分析》期终总结&《Linux及安全》期中总结

    <Linux内核分析>期终总结&<Linux及安全>期中总结 [李行之 原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc. ...

  6. Linux内核分析第三周学习总结

    Linux内核源码简介 arch/ 该目录中包含和硬件体系结构相关的代码,每种平台占一个相应的目录. 和32位PC相关的代码存放在x86目录下. 每种平台至少包含3个子目录:kernel(存放支持体系 ...

  7. Linux内核设计与实现 第三章

    1. 进程和线程 进程和线程是程序运行时状态,是动态变化的,进程和线程的管理操作都是由内核来实现的. Linux中的进程于Windows相比是很轻量级的,而且不严格区分进程和线程,线程不过是一种特殊的 ...

  8. 关于五子棋游戏java版

    一 题目简介:关于五子棋游戏 二 源码的github链接   https://github.com/marry1234/test/blob/master/五子棋游戏 三.所设计的模块测试用例.测试结果 ...

  9. 递归拼装Tree结构数据

    @Override public List<Map<String, Object>> queryListTree() { List<Map<String,Objec ...

  10. Java 模仿 C# 字典 一例

    List<Map.Entry<Integer, String>> orderStatusList = new ArrayList<Map.Entry<Integer ...