POJ 1986 - Distance Queries - [LCA模板题][Tarjan-LCA算法]
题目链接:http://poj.org/problem?id=1986
Description
Input
* Line 2+M: A single integer, K. 1 <= K <= 10,000
* Lines 3+M..2+M+K: Each line corresponds to a distance query and contains the indices of two farms.
Output
Sample Input
7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6
Sample Output
13
3
36
Hint
题意:
输入第1~M+1行,与POJ 1984相同,代表了农场地图。
然后再一行有一个整数K代表询问数,
再然后有K个询问u和v之间最短距离。
题解:
本题的输入确定了农场地图是一棵树,并且本题不需要知道农场之间的位置关系,所以不需要记录东西南北。
树上两点间的最短距离,有两种情况:
①u是v的祖先,则dist(u,v) = dist(root,v) - dist(root,u)
②u不是v的祖先,那么从u到v必然要经过LCA(u,v),显然就是最短路径,则dist(u,v) = dist(root,u) - dist(root,LCA(u,v)) + dist(root,v) - dist(root,LCA(u,v))
不难发现,第①种情况下,dist(root,LCA(u,v)) = dist(root,u),那么①和②就可以统一为:dist(u,v) = dist(root,u) + dist(root,v) - 2 * dist(root,LCA(u,v))
所以我们只要计算出每个节点和树根的距离,求出所有查询(u,v)的LCA(u,v),就能得到dist(u,v)。
AC代码:
#include<cstdio>
#include<vector>
using namespace std; const int maxn=+; //节点数
const int maxm=+; //边数
const int maxq=+; //查询数 int par[maxn];
int find(int x){return (par[x]==x)?x:(par[x]=find(par[x]));} struct Edge{
int u,v,w;
Edge(int u=,int v=,int w=){this->u=u,this->v=v,this->w=w;}
};
vector<Edge> E;
vector<int> Ge[maxn];
void addedge(int u,int v,int w)
{
E.push_back(Edge(u,v,w));
Ge[u].push_back(E.size()-);
} struct Query{
int u,v;
int lca;
Query(int u=,int v=,int lca=){this->u=u,this->v=v,this->lca=lca;}
};
vector<Query> Q;
vector<int> Gq[maxn];
void addquery(int u,int v)
{
Q.push_back(Query(u,v));
Gq[u].push_back(Q.size()-);
} bool vis[maxn];
int dist[maxn];
void LCA(int u,int d)
{
par[u]=u; //建立以u为代表元素的集合
vis[u]=;
dist[u]=d;
for(int i=;i<Ge[u].size();i++)
{
Edge &e=E[Ge[u][i]]; int v=e.v;
if(!vis[v])
{
LCA(v,d+e.w);
par[v]=u; //将v的集合并入u的集合
}
}
for(int i=;i<Gq[u].size();i++)
{
Query &q=Q[Gq[u][i]]; int v=q.v;
if(vis[v])
{
q.lca=find(v);
Q[Gq[u][i]^].lca=q.lca;
}
}
} int m,n,k;
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int u,v,w; char d[];
scanf("%d%d%d%s",&u,&v,&w,d);
addedge(u,v,w);
addedge(v,u,w);
} scanf("%d",&k);
for(int i=;i<=k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addquery(u,v);
addquery(v,u);
} LCA(,); for(int i=;i<=k;i++)
{
printf("%d\n",dist[Q[(i-)*].u]+dist[Q[(i-)*].v]-*dist[Q[(i-)*].lca]);
}
}
POJ 1986 - Distance Queries - [LCA模板题][Tarjan-LCA算法]的更多相关文章
- POJ.1986 Distance Queries ( LCA 倍增 )
POJ.1986 Distance Queries ( LCA 倍增 ) 题意分析 给出一个N个点,M条边的信息(u,v,w),表示树上u-v有一条边,边权为w,接下来有k个询问,每个询问为(a,b) ...
- POJ 1986 Distance Queries LCA两点距离树
标题来源:POJ 1986 Distance Queries 意甲冠军:给你一棵树 q第二次查询 每次你问两个点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + d ...
- POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)
POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 [USACO]距离咨询(最近公共祖先) Description F ...
- POJ 1986 Distance Queries 【输入YY && LCA(Tarjan离线)】
任意门:http://poj.org/problem?id=1986 Distance Queries Time Limit: 2000MS Memory Limit: 30000K Total ...
- POJ 1986 Distance Queries(LCA Tarjan法)
Distance Queries [题目链接]Distance Queries [题目类型]LCA Tarjan法 &题意: 输入n和m,表示n个点m条边,下面m行是边的信息,两端点和权,后面 ...
- POJ 1470 Closest Common Ancestors (模板题)(Tarjan离线)【LCA】
<题目链接> 题目大意:给你一棵树,然后进行q次询问,然后要你统计这q次询问中指定的两个节点最近公共祖先出现的次数. 解题分析:LCA模板题,下面用的是离线Tarjan来解决.并且为了代码 ...
- POJ 1330 Nearest Common Ancestors (模板题)【LCA】
<题目链接> 题目大意: 给出一棵树,问任意两个点的最近公共祖先的编号. 解题分析:LCA模板题,下面用的是树上倍增求解. #include <iostream> #inclu ...
- POJ 1986 Distance Queries(Tarjan离线法求LCA)
Distance Queries Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 12846 Accepted: 4552 ...
- poj 1986 Distance Queries 带权lca 模版题
Distance Queries Description Farmer John's cows refused to run in his marathon since he chose a pa ...
随机推荐
- sql server 存储过程基础知识
转自家园大哥博文http://www.cnblogs.com/jiajiayuan/archive/2011/06/15/2081201.html 什么是存储过程呢?存储过程就是作为可执行对象存放在数 ...
- java痛苦学习之路[十]--日常问题汇总
FIddler2 1.FIddler2 request请求的參数出现中文乱码问题时,须要进行一下设置: 打开注冊表编辑器,找到HKCU\Software\Microsoft\Fiddler 2\,在 ...
- 删除腾讯游戏助手自动生成的文件aow_drv.log
解决办法: 管理员身份运行cmd,依次执行如下指令: net stop aow_drvdel C:\aow_drv.logmkdir C:\aow_drv.logattrib +s +h C:\aow ...
- 04python while循环语句
使用while ture语法 luck_num = 33 flag = True while flag: guess_num = input('请输入您猜测的年龄:') if guess_num &l ...
- CMake区分32位64位
IF(CMAKE_CL_64) set(platform x64) ELSE(CMAKE_CL_64) set(platform x86) ENDIF(CMAKE_CL_64)
- U3D教程宝典之两步实现超实用的XML存档
两步实现超实用的XML存档 本套存档的优点:易使用,跨平台,防作弊(内容加密 + 防拷贝) 脚本下载地址 使用方法非常简单:把GameDataManager和XmlSaver两个脚本添加至工程后(1) ...
- mybatis 之 parameterType="java.util.HashMap">
/** * 根据goods_no 和 goods_id 来查询商品信息 * * @param goodsNos * @return */ public List<Goods> getGoo ...
- python--列表内建函数的方法
List Method Operation list.append(obj) #向列表中添加一个对象obj list.count(obj) #返回一个对象obj 在列表中出现的次数 ...
- 【摘抄】C++程序员练级攻略
摘抄自互联网文章 作为C++程序员,或者说程序员一定要提升自己: 专访李运华:程序员如何在技术上提升自己-CSDN.NET专访徐宜生:坚决不做代码搬运工!-CSDN.NET 上面两个文章我觉得都不错. ...
- iText7生成pdf
1 官网 http://developers.itextpdf.com/itext-java 2 form中加入表格 http://developers.itextpdf.com/content/be ...