hdu6115 Factory (LCA + 倍增)
Factory
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 399 Accepted Submission(s): 138
Problem Description
现在百度陆续开了许许多多的子公司。每家子公司又会在各城市中不断兴建属于该子公司的办公室。
由于各个子公司之间经常有资源的流动,所以公司员工常常想知道,两家子公司间的最小距离。
我们可以把子公司看成一个由办公室组成的集合。那么两个子公司A和B的最小距离定义为min(dist(x,y))(x∈A,y∈B)。其中dist(x,y)表示两个办公室之间的最短路径长度。
现在共有Q个询问,每次询问分别在两个子公司间的最小距离。
Input
对于每组数据:
第一行两个正整数N和M。城市编号为1至N,子公司编号为1至M。
接下来N-1行给定所有道路的两端城市编号和道路长度。
接下来M行,依次按编号顺序给出各子公司办公室所在位置,每行第一个整数G,表示办公室数,接下来G个数为办公室所在位置。
接下来一个整数Q,表示询问数。
接下来Q行,每行两个正整数a,b(a不等于b),表示询问的两个子公司。
【数据范围】
0<=边权<=100
1<=N,M,Q,工厂总数<=100000
Output
Sample Input
Sample Output
0
0
题意:
求树上最短路。
思路:
差不多裸的LCA,这里就当总结LCA的倍增实现了。
dfs求出每个节点的深度及到根节点的距离,并记录每个节点的第 (1<<i) 个祖先,这里和RMQ思想类似;
求LCA时先找到较深的节点(设为 u)与较浅的节点(设为 v)同高度的祖先,在由上至下找两节点第一个不同的祖先,则上一个祖先就是 u、v 的祖先。
代码:
- #include<iostream>
- #include<cstdio>
- #include<vector>
- #include<cstring>
- using namespace std;
- const int maxn = 1e5+5, INF = 2e9+7;
- class Edge
- {
- public:
- int u, v, w;
- Edge(int a, int b, int c):u(a), v(b), w(c)
- {
- }
- };
- int n, m, q;
- int deep[maxn], up[maxn][20], dis[maxn];
- vector<Edge> edges;
- vector<int> grap[maxn], factory[maxn];
- void AddEdge(int u, int v, int w)
- {
- grap[u].push_back(edges.size());
- edges.push_back(Edge(u, v, w));
- grap[v].push_back(edges.size());
- edges.push_back(Edge(v, u, w));
- }
- void Init()
- {
- cin>>n>>m;
- edges.clear();
- memset(up, 0, sizeof(up));
- for(int i=0; i<=n; ++i)
- {
- dis[i]=0;
- factory[i].clear();
- grap[i].clear();
- deep[i]=0;
- }
- for(int i=1; i<n; ++i)
- {
- int u, v, w;
- cin>>u>>v>>w;
- AddEdge(u, v, w);
- }
- for(int i=1; i<=m; ++i)
- {
- int r, a;
- cin>>r;
- while(r--)
- {
- cin>>a;
- factory[i].push_back(a);
- }
- }
- }
- void Dfs(int u, int fa, int dep, int d)
- {
- deep[u]=dep;
- dis[u]=d;
- for(int i=1; i<20; ++i)//u 的第(1<<i)个祖先是 up[u][i-1] 的第(1<<(i-1))个祖先
- up[u][i]=up[up[u][i-1]][i-1];
- for(int i=0; i<grap[u].size(); ++i)
- {
- Edge& e=edges[grap[u][i]];
- if(e.v==fa) continue;
- up[e.v][0]=u;
- Dfs(e.v, u, dep+1, d+e.w);
- }
- }
- int LCA(int u, int v)
- {
- if(deep[u] < deep[v]) swap(u, v);
- int k=deep[u]-deep[v];
- for(int i=0; i<20; ++i)//到同一高度
- if((1<<i)&k)
- u=up[u][i];
- if(u!=v)
- {
- for(int i=19; i>=0; --i)
- {
- if(up[u][i]!=up[v][i])
- {
- u=up[u][i];
- v=up[v][i];
- }
- }
- u=up[u][0];
- }
- return u;
- }
- int GetDist(int u, int v)
- {
- int lca=LCA(u, v);
- return dis[u]+dis[v]-2*dis[lca];
- }
- void Solve()
- {
- Dfs(1, -1, 0, 0);
- cin>>q;
- while(q--)
- {
- int a, b;
- cin>>a>>b;
- int ans=INF;
- for(int i=0; i<factory[a].size(); ++i)
- {
- if(ans==0) break;
- for(int j=0; j>factory[b].size(); ++j)
- {
- if(ans==0) break;
- if(factory[a][i]==factory[b][j])
- {
- ans=0;
- break;
- }
- }
- }
- for(int i=0; i<factory[a].size(); ++i)
- {
- if(ans==0) break;
- for(int j=0; j<factory[b].size(); ++j)
- {
- if(ans==0) break;
- int MinDist=GetDist(factory[a][i], factory[b][j]);
- ans=min(ans, MinDist);
- }
- }
- cout<<ans<<endl;
- }
- }
- int main()
- {
- int t;
- cin>>t;
- while(t--)
- {
- Init();
- Solve();
- }
- return 0;
- }
hdu6115 Factory (LCA + 倍增)的更多相关文章
- 【codevs2370】小机房的树 LCA 倍增
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...
- LCA倍增算法
LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...
- 洛谷 3379 最近公共祖先(LCA 倍增)
洛谷 3379 最近公共祖先(LCA 倍增) 题意分析 裸的板子题,但是注意这题n上限50w,我用的边表,所以要开到100w才能过,一开始re了两发,发现这个问题了. 代码总览 #include &l ...
- CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)
CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天, ...
- POJ.1986 Distance Queries ( LCA 倍增 )
POJ.1986 Distance Queries ( LCA 倍增 ) 题意分析 给出一个N个点,M条边的信息(u,v,w),表示树上u-v有一条边,边权为w,接下来有k个询问,每个询问为(a,b) ...
- POJ.1330 Nearest Common Ancestors (LCA 倍增)
POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...
- LCA(倍增在线算法) codevs 2370 小机房的树
codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...
- LCA(最近公共祖先)——LCA倍增法
一.前人种树 博客:最近公共祖先 LCA 倍增法 博客:浅谈倍增法求LCA 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 代码: const int MAXN ...
- POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)
1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...
- 次小生成树(LCA倍增)
算法: 求出MST之后枚举每条在MST之外的边 连上之后会出现环 找到环中除加上的边之外权值最大的边 删除该边之后得到一颗新树 做法: 利用LCA倍增地维护最小生成树上两点之间的最大边权 每次枚举在M ...
随机推荐
- Linux下用户的创建与删除
我们在Linux下创建用户主要有两种方式:adduser和useradd,它们的区别以及主要用法如下: adduser adduser的用法很简单,只需adduser+username即可,如下: s ...
- Orchard Core创建CMS/Blog站点
安装.NET Core SDK 下载并安装当前最新版本.NET Core SDK 3.1: https://dotnet.microsoft.com/download 安装visual studio ...
- Aop的学习与使用
什么是aop AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一 ...
- 有关java反射的几个小方法的作用和区别
1.Class类中 getXXX()和getDeclaredXXX()的作用和区别: 前者获取某个类的所有公共(public)的字段(or方法or构造函数),包括父类.后者获取所有的字段(or方法or ...
- IPSecVPN介绍 & (Cisco Packet Tracer)IPSecVPN实验演示
一.基础知识 VPN(Virtual Private Network)虚拟专有网络,即虚拟专网.VPN可以实现在不安全的网络上,安全的传输数据,好像专网!VPN只是一个技术,使用PKI技术,来保证数据 ...
- spring的aop编程(半自动、全自动)
1.spring的半自动代理(从spring中获取代理对象) (1)spring中的通知类型 spring中aop的通知类型有五种: 前置:在目标方法执行前实施加强 后置:在目标方法执行后实施加强 环 ...
- 使用VMware虚拟机安装RHEL7(RedHat Enterprise Linux7)步骤
准备工具: 1.VMware Workstation 14 2.RedHat Enterprise Linux 7.0镜像文件 在虚拟机内设置操作系统的硬件标准 单击"创建新的虚拟机&quo ...
- 不知如何创建UML电路图?看看本文
Visual Paradigm是包含设计共享.线框图和数据库设计新特性的企业项目设计工具.现在你只需要这样单独的一款模型软件 Visual Paradigm就可以完成用UML设计软件,用BPMN去执行 ...
- Matlab中imagesc用法
来源:https://ww2.mathworks.cn/help/matlab/ref/imagesc.html?searchHighlight=imagesc&s_tid=doc_srcht ...
- 小程序将base64的多张图片,传到tp5后台
zhu要是前端传过来的数据是base64的数据库存储不了base64的数据,因存储量太过于大,因此后台要将base64的数据转换成,34124323534.jpg等格式的,数据库才可将其存储 源码暂时 ...