POJ 1986 Distance Queries (最近公共祖先,tarjan)
本题目输入格式同1984,这里的数据范围坑死我了!!!1984上的题目说边数m的范围40000,因为双向边,我开了80000+的大小,却RE。
后来果断尝试下开了400000的大小,AC。
题意:给出n个点,m条边。
接下来m行,每行对应u,v,len,字符(字符表示v位于u的哪个方向,在本题没有丝毫用处)
表示u和v的路径长度为len。注意本题是双向边!
给出k个查询,让你求两点间的距离。
思路:可以这样处理:先处理出每个节点i到根的距离dist[i]。
设根节点1到a的路径和1到b的路径的最后一个相同的节点为u,即a和b的最近公共祖先。
那么a和b之间的路径为au+ub。
au+ub=au+dis[u]+ub+dis[u]-2*dis[u]=dis[a]+dis[b]-2*dis[LCA(a,b)]
求最近公共祖先用tarjan算法
还有就是一开始不知道如何将两点之间的距离和对应的查询联系起来,参考了别人的思路后,恍然大悟。
在存储所要查询的内容时,同时记录对应的编号,之后再求LCA时只要将距离存入索引为对应编号的数组中去即可,详细情况见代码吧。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <math.h>
#include <map> using namespace std;
const int maxn=;
const int INF=0x3f3f3f3f;
int n,m,k;
int head[maxn];
int tot=;
int dis[maxn]; //存储节点到根节点1的距离
int vis[maxn]={}; //用于LCA中的标记
int vis2[maxn]={}; //用于标记是否被访问过
int result[]; struct Query{
int u;
int id; //该查询对应的编号
}; vector<Query>link[maxn]; struct Edge{
int next,to,length;
}edge[maxn*];
//POJ1984上面说边数大小最多40000,由于双向边,我开了80000+,结果RE,后来开了10倍,才AC。。。 void add(int u,int v,int l){
edge[tot].next=head[u];
edge[tot].to=v;
edge[tot].length=l;
head[u]=tot++; edge[tot].next=head[v];
edge[tot].to=u;
edge[tot].length=l;
head[v]=tot++;
}
struct UF{
int fa[maxn];
void init(){
for(int i=;i<maxn;i++)
fa[i]=i;
}
int find_root(int x){
if(fa[x]!=x)
fa[x]=find_root(fa[x]);
return fa[x];
}
void Union(int u,int v){
int x=find_root(u);
int y=find_root(v);
fa[y]=x;
}
}uf; void LCA(int u){
vis2[u]=;
for(int k=head[u];k!=-;k=edge[k].next){
int v=edge[k].to;
if(!vis2[v]){
LCA(v);
uf.Union(u,v);
}
}
int v,idx,anc;
vis[u]=;
for(int i=;i<link[u].size();i++){
v=link[u][i].u;
if(vis[v]){
//idx是u和v所对应的第几个询问
idx=link[u][i].id;
anc=uf.fa[uf.find_root(v)];
result[idx]=dis[u]+dis[v]-*dis[anc];
}
}
}
void dfs(int u,int l){
vis2[u]=;
dis[u]=l;
for(int k=head[u];k!=-;k=edge[k].next){
if(!vis2[edge[k].to])
dfs(edge[k].to,l+edge[k].length);
}
}
int main()
{
int u,v,l;
char str[];
memset(dis,,sizeof(dis));
memset(head,-,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%d%d%d%s",&u,&v,&l,str);
add(u,v,l);
add(v,u,l);
}
cin>>k;
Query tmp;
for(int i=;i<=k;i++){
scanf("%d%d",&u,&v);
tmp.u=v;tmp.id=i; //这个方法妙啊,在存储查询内容时,记录下对应的编号。
link[u].push_back(tmp);
tmp.u=u;
link[v].push_back(tmp);
}
memset(vis2,,sizeof(vis2));
//先求各节点到根节点的距离
dfs(,);
uf.init();
memset(vis2,,sizeof(vis2));
//LCA求最近公共祖先
LCA();
for(int i=;i<=k;i++){
printf("%d\n",result[i]);
}
return ;
}
POJ 1986 Distance Queries (最近公共祖先,tarjan)的更多相关文章
- 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 LCA两点距离树
标题来源:POJ 1986 Distance Queries 意甲冠军:给你一棵树 q第二次查询 每次你问两个点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + d ...
- 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 【输入YY && LCA(Tarjan离线)】
任意门:http://poj.org/problem?id=1986 Distance Queries Time Limit: 2000MS Memory Limit: 30000K Total ...
- POJ 1986 Distance Queries (Tarjan算法求最近公共祖先)
题目链接 Description Farmer John's cows refused to run in his marathon since he chose a path much too lo ...
- POJ 1986 Distance Queries(Tarjan离线法求LCA)
Distance Queries Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 12846 Accepted: 4552 ...
- POJ 1986 Distance Queries(LCA Tarjan法)
Distance Queries [题目链接]Distance Queries [题目类型]LCA Tarjan法 &题意: 输入n和m,表示n个点m条边,下面m行是边的信息,两端点和权,后面 ...
- POJ - 1986 Distance Queries(离线Tarjan算法)
1.一颗树中,给出a,b,求最近的距离.(我没考虑不联通的情况,即不是一颗树的情况) 2.用最近公共祖先来求, 记下根结点到任意一点的距离dis[],这样ans = dis[u] + dis[v] - ...
- POJ 1986 - Distance Queries - [LCA模板题][Tarjan-LCA算法]
题目链接:http://poj.org/problem?id=1986 Description Farmer John's cows refused to run in his marathon si ...
随机推荐
- Linux环境下常用regexp的使用
正则表达式 REGular EXPression 的简写元字符 匹配次数 位置锚定 分组 --------------------------------------元字符. 匹配任意单个字符 [ ...
- 【转】Hibernate入门实例
1. 环境配置 1.1 hiberante环境配置 hibernate可实现面向对象的数据存储.hibernate的官网:http://hibernate.org/ 官网上选择hibernate OR ...
- DB2数据库之间联邦
现在有以下两个数据库:sample,QIN 需要在数据库QIN中访问sample中的表ACT 1.数据库编目 C:\Users\QIN>db2 catalog tcpip node OLIVER ...
- Redis 四:存储类型之有序集合
有序集合似乎更大的操作是由于加了一个叫做“分子”的东西 事实上就好像普通的数据,只是为这个数据加了一个纯数字的标识, 通过操作这些标识来得到我们想要的数据! 分子可以是整形,也可以是双精度浮点型: = ...
- SecurityManager一:理解AccessController.doPrivileged()
AccessController.checkPermission()检测模型: 从VM Stack的current stack frame起逐个检测stack frome所指class的protect ...
- boa介绍文档
http://wenku.baidu.com/view/873aa903cc175527072208ce.html?re=view
- SharePoint 2010 中使用Ztree和EasyUI样式冲突问题
<style type="text/css"> /*解决ztree和SharePoint样式冲突问题*/ .ztree li a { display: inline-b ...
- Qt隐藏标题栏
setWindowFlags (Qt::CustomizeWindowHint)setWindowFlags (Qt::FramelessWindowHint)两个函数都可以去掉标题栏,区别是第一个可 ...
- 用Sqlplus手动创建Oracle11g数据库
用Sqlplus手动创建Oracle数据库 刚开始学习Oracle数据库,菜鸟一个,使用sqlplus创建数据库遇到了很多问题,通过不断地百度,终于创建成功了.所以顺便把整个过程中犯的一些最低级的错误 ...
- Teamwork——Week 4 Daily Scrum Meeting#1 2013.10.23
一.会议议题 1)根据确立的项目题目,进一步明确PM,DEV,TEST的工作. 2)确定团队分工和预估项目时间. 3)完成项目架构NABC模型. 4)确定第一轮开发团队分工 二.会议时间 2013年1 ...