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 ...
随机推荐
- Java Collections Source Code Series 2 ---接口
废话开篇 自己学完Java Collections框架之后,其中的一个较大的收获就是接口对于层次的重要性.Java Collections的最终实现至少有几十个,其中很多都有非常相似的功能(metho ...
- Http协议[Get和Post]详解
(2012-11-27 11:23:26) 标签: android http get post mars 分类: Android系列 访问url,需要连接网络.所以,首先应该添加Manifest权限: ...
- 先登陆面试再者Tabs标签导航,多次网络请求共享cookie,本地存储cookie
1,index.ng.html: <head> <title>ionic todo example</title> </head> <body n ...
- Spring Roo
Spring Roo 是SpringSource新的开放源码技术,该技术主要面向企业中的Java开发者,使之更富有成效和愉快的进行开发工作,而不会牺牲工程完整或灵活性.无论你是一个新的Java开发人员 ...
- Go原子计数
通过原子计数可以在多线程情况下,对同一个数值进行加减操作,一般用于状态同步. 先看代码: package main import "fmt" import "time&q ...
- Oracle 11gR2 Database和Active Data Guard迁移案例
客户一套核心系统由一台Oracle Database 11.2.0.3.4单机和一台Active Data Guard组成,分别运行在两台PC服务器上,Oracle Linux 5.8 x86_64b ...
- UIBezierPath 的使用介绍
使用UIBezierPath类可以创建基于矢量的路径.此类是Core Graphics框架关于path的一个封装.使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状 ...
- Linux后门入侵检测
蛋疼啊,服务器被入侵成肉鸡了,发出大量SYN请求到某个网站!(瞬间有种被OOXX(强)(奸)的赶脚) 泪奔ING... 源起: Linux服务器日常检查,#ps aux 发现大量httpd进程,和往常 ...
- mysql数据库编码设置成utf-8,避免出现乱码
设置默认编码为utf8:set names utf8;设置数据库db_name默认为utf8:ALTER DATABASE `db_name` DEFAULT CHARACTER SET utf8 C ...
- h264码流分析
---------------------------------------------------------------------------------------------------- ...