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省简化为由N个城市组成,某些城市之间存在双向道路,而且A省的交通有一个特点就是任意两个城市之间都能通过道路相互到达,且在不重复经过城市的情况下任意两个城市之间的到达方案都是唯一的。聪明的你一定已经发现,这些城市构成了树这样一个结构。

现在百度陆续开了许许多多的子公司。每家子公司又会在各城市中不断兴建属于该子公司的办公室。

由于各个子公司之间经常有资源的流动,所以公司员工常常想知道,两家子公司间的最小距离。
我们可以把子公司看成一个由办公室组成的集合。那么两个子公司A和B的最小距离定义为min(dist(x,y))(x∈A,y∈B)。其中dist(x,y)表示两个办公室之间的最短路径长度。

现在共有Q个询问,每次询问分别在两个子公司间的最小距离。
 

Input

第一行一个正整数T,表示数据组数。

对于每组数据:

第一行两个正整数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

1
3 3
1 2 1
2 3 1
2 1 1
2 2 3
2 1 3
3
1 2
2 3
1 3

Sample Output

1
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 + 倍增)的更多相关文章

  1. 【codevs2370】小机房的树 LCA 倍增

    2370 小机房的树  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...

  2. LCA倍增算法

    LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...

  3. 洛谷 3379 最近公共祖先(LCA 倍增)

    洛谷 3379 最近公共祖先(LCA 倍增) 题意分析 裸的板子题,但是注意这题n上限50w,我用的边表,所以要开到100w才能过,一开始re了两发,发现这个问题了. 代码总览 #include &l ...

  4. CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)

    CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天, ...

  5. POJ.1986 Distance Queries ( LCA 倍增 )

    POJ.1986 Distance Queries ( LCA 倍增 ) 题意分析 给出一个N个点,M条边的信息(u,v,w),表示树上u-v有一条边,边权为w,接下来有k个询问,每个询问为(a,b) ...

  6. POJ.1330 Nearest Common Ancestors (LCA 倍增)

    POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...

  7. LCA(倍增在线算法) codevs 2370 小机房的树

    codevs 2370 小机房的树 时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...

  8. LCA(最近公共祖先)——LCA倍增法

    一.前人种树 博客:最近公共祖先 LCA 倍增法 博客:浅谈倍增法求LCA 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 代码: const int MAXN ...

  9. POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)

    1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...

  10. 次小生成树(LCA倍增)

    算法: 求出MST之后枚举每条在MST之外的边 连上之后会出现环 找到环中除加上的边之外权值最大的边 删除该边之后得到一颗新树 做法: 利用LCA倍增地维护最小生成树上两点之间的最大边权 每次枚举在M ...

随机推荐

  1. 集群实战(1):swarm安装记述

    查看主机名 hostnamectl 修改主机名 hostnamectl set-hostname xxx 关闭selinux sed -i 's/SELINUX=enforcing/#SELINUX= ...

  2. Git+Gitlab+Ansible剧本实现一键部署动态网站(5)

    项目前言 之前已经写了一篇关于git和ansible的博客<Git+Gitlab+Ansible剧本实现一键部署Nginx–技术流ken>.关于git,gitliab,ansible在我以 ...

  3. Mock简明文档

    Mock简明文档 Mock.mock() Mock.mock( requestUrl?, requestType?, template|function(options) ) Mock.mock( t ...

  4. Flutter 使用image_gallery_saver保存图片

    Flutter  使用image_gallery_saver保存图片 其实我们开发项目app的时候, 你会发现有很多问题, 比如保存图片功能时 ,不仅导入包依赖包: image_gallery_sav ...

  5. CTF-BugKu-WEB-35-41

    2020.09.19 go on,今天务必搞定web 经验教训 能运行php标签的扩展名有php4,phtml,phtm,phps,php5等,可以在php被过滤的时候尝试: html请求头中,对内容 ...

  6. spring mvc(4) HandlerMapping

    在前面一节里提到,DispatcherServlet在接收到请求后,通过HandlerMapping找到处理请求对应的Controller(其实处理请求器并不一定是Controller,还可以是Htt ...

  7. kubernetes部署Percona XtraDB Cluster集群

    PXC介绍 全称percona-xtradb-cluster,提供了MySQL高可用的一种实现方法.PXC集群以节点组成(推荐至少3节点,便于故障恢复),每个节点都是基于常规的 MySQL Serve ...

  8. 浅谈SSRF

    前言 最近主要是在思考考研的事.还是没想好-- 这几天的话写了一篇简单代审投稿了星盟,看了会SSRF.今天简单写下SSRF. 本文所有思路均来自互联网,并没有新想法.仅仅只是做个记录. 本文可能会有大 ...

  9. 测试工具-XPath使用

    XML有两种MIME类型,即application/xml和text/xml,在HTTP中,MIME Type类型被定义在Content-Type header中.我们经常也会看到接口返回数据类型为X ...

  10. 初探JVM

    JVM探究 请你谈谈你对JVM的理解?java8虚拟机和之前的变化更新? 什么是OOM,什么是栈溢出StackOverFlowError?怎么分析? JVM的常用调优参数? 内存快照如何抓取,怎么分析 ...