1. 整整花了一天学习了LCA,tarjan的离线算法,就切了2个题。
  2. 第一题,给一棵树,一次查询,求LCA。2DFS+并查集,利用深度优先的特点,回溯的时候U和U的子孙的LCA是U,U和U的兄弟结点的子孙们的LCA是U的父亲,结合每次询问,

   3.   hdu2586,求无相无环有权图,求俩点距离(n<=40000,最短路必然TLE),转化树(任意取一点为根),双向边保存,链式前向星保存边和权,DfS,

先记录下每次询问,用链式前向星保存,双向保存,第(i+1)/2条边即为第i次询问(一次询问记为双向边),最后用一个数组ans[i][3]来记录,ans[i][0]:第i次询问起点,依次ans[i][1],终点,ans[i][2],他们的LCA。DIS【i】,表根到I的距离,最后:dis[u]+dis[v]-2*dis[lca[u,v]]即可。

#include<iostream>  //只求一次询问 1330,水
#include<vector>
#include<cstdio>
using namespace std;
vector<vector<int> >edge(10001);
int from,to;int n; bool mark=0;
int fa[10001];int visited[10001];
int find(int x){return fa[x]=(x==fa[x]?x:find(fa[x]));} //压缩路劲
void readin()
{
scanf("%d",&n); mark=0;
for(int i=0;i<=n;i++) //初始化
{
visited[i]=1;
fa[i]=i;
edge[i].clear();
}
int begin,end;
for(int i=0;i<n-1;i++)
{
scanf("%d%d",&begin,&end);
edge[begin].push_back(end);
visited[end]=0; //不是根,这样标记出根。
}
scanf("%d%d",&from,&to);
}
void tarjan(int u)
{ int len=edge[u].size();
for(int i=0;i<len;i++)
{
int v=edge[u][i];
if(visited[v]==0)
{
tarjan(v);
if(mark)return;
fa[v]=u; //合并之
}
}
visited[u]=1; //回溯时标记!!!!!这时候表明它和它的孩子都已经被标记,离线LCA这样。
if(u==from&&visited[to]) //查询询问,另外一个点是否已经访问,若访问了,以find(v)为他们的LCA
{
mark=1;
printf("%d\n",find(to));return;
}
if(u==to&&visited[from])
{
mark=1;
printf("%d\n",find(from));return;
}
}
int main()
{
int tcase;scanf("%d",&tcase);
while(tcase--)
{
readin();
for(int i=1;i<=n;i++)
{
if(visited[i]) //从根开使
{
visited[i]=0; //此处不忘把根标记回来!
tarjan(i);
break;
}
}
}
return 0;
}
#include<iostream>  //46MS(G++)     会了就水了,DIF 2
#include<vector> //o(n+q)
#include<cstdio>
using namespace std;
struct edges //边集
{
int pre,to,w;
};
struct querys //询问的边
{
int pre,to;
};
int n; int num_query;
int fa[40001];int visited[40001];
int dis[40001];int head[40001];int head2[40001];
int res[201][3];
vector<querys>que(401);
vector<edges>edge(80001);
int find(int x){return fa[x]=(x==fa[x]?x:find(fa[x]));} //并查集+压缩路径优化之
void readin()
{
scanf("%d%d",&n,&num_query);
for(int i=0;i<=n;i++) //初始化,
{
head[i]=head2[i]=-1;
visited[i]=0;
fa[i]=i;
dis[i]=0;
}
int begin,end,w;
for(int i=0;i<2*(n-1);i++) //读入边和询问,都双向读入
{
scanf("%d%d%d",&begin,&end,&w);
edge[i].to=end;
edge[i].w=w;
edge[i].pre=head[begin];
head[begin]=i;
i++;
edge[i].to=begin;
edge[i].w=w;
edge[i].pre=head[end];
head[end]=i;
}
for(int i=1;i<=2*num_query;i++) //询问也双向读入,防止只有一头的情况
{
scanf("%d%d",&begin,&end);
que[i].to=end;
que[i].pre=head2[begin];
head2[begin]=i;
i++;
que[i].to=begin;
que[i].pre=head2[end];
head2[end]=i;
}
}
void tarjan(int u,int father) //算法关键.
{
for(int i=head[u];i!=-1;i=edge[i].pre)
{
int v=edge[i].to;
if(visited[v]==0&&v!=father) //不回走(father) {
dis[v]=dis[u]+edge[i].w; //沿路记录长度
tarjan(v,u); //递归
fa[v]=u; //合并之
}
}
visited[u]=1; //回溯时标记(标记了说明该店已经有祖先fa[u]值),
for(int i=head2[u];i!=-1;i=que[i].pre) //遍历询问U的边,若有询问。用前向星可以记录询问的编号又能降低复杂度(直接访问U来走)
{
if(visited[que[i].to])
{
res[(i+1)/2][0]=u; //记录起点,终点,他们的LCA,询问的编号(次序)是(i+1)/2
res[(i+1)/2][1]=que[i].to;
res[(i+1)/2][2]= find(que[i].to);
}
}
}
int main()
{
int tcase;scanf("%d",&tcase);
while(tcase--)
{
readin();
tarjan(1,-1);
for(int i=1;i<=num_query;i++)
{
printf("%d\n",dis[res[i][0]]+dis[res[i][1]]-2*dis[res[i][2]]);
}
//printf("\n");
}
return 0;
}

poj1330+hdu2586 LCA离线算法的更多相关文章

  1. Tarjan的LCA离线算法

    LCA(Least Common Ancestors)是指树结构中两个结点的最低的公共祖先.而LCA算法则是用于求两个结点的LCA.当只需要求一对结点的LCA时,我们很容易可以利用递归算法在O(n)的 ...

  2. Closest Common Ancestors---poj1470(LCA+离线算法)

    题目链接:http://poj.org/problem?id=1470 题意是给出一颗树,q个查询,每个查询都是求出u和v的LCA:    以下是寻找LCA的预处理过程: void LCA(u){ f ...

  3. HDU 2874 Connections between cities(LCA离线算法实现)

    http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意: 求两个城市之间的距离. 思路: LCA题,注意原图可能不连通. 如果不了解离线算法的话,可以看我之 ...

  4. LCA离线算法Tarjan详解

    离线算法也就是需要先把所有查询给保存下来,最后一次输出结果. 离线算法是基于并查集实现的,首先就是初始化P[i] = i. 接下来对于每个点进行dfs: ①首先判断是否有与该点有关的查询,如果当前该点 ...

  5. 距离LCA离线算法Tarjan + dfs + 并查集

    距离B - Distance in the Tree 还是普通的LCA但是要求的是两个节点之间的距离,学到了一些 一开始我想用带权并查集进行优化,但是LCA合并的过程晚于离线计算的过程,所以路径长度会 ...

  6. LCA离线算法Tarjan的模板

    hdu 2586:题意:输入n个点的n-1条边的树,m组询问任意点 a b之间的最短距离 思路:LCA中的Tarjan算法,RMQ还不会.. #include <stdio.h> #inc ...

  7. HDU 2874 LCA离线算法 tarjan算法

    给出N个点,M条边.Q次询问 Q次询问每两点之间的最短距离 典型LCA 问题   Marjan算法解 #include "stdio.h" #include "strin ...

  8. POJ1986 DistanceQueries 最近公共祖先LCA 离线算法Tarjan

    这道题与之前那两道模板题不同的是,路径有了权值,而且边是双向的,root已经给出来了,就是1,(这个地方如果还按之前那样来计算入度是会出错的.数据里会出现多个root...数据地址可以在poj的dis ...

  9. 1128 - Greatest Parent---LightOj(LCA+离线算法)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1128 给你一颗树,树的每个节点都有一个权值,树根是节点0,权值为1,树中每个节点的权值 ...

随机推荐

  1. Hibernate中的inverse和cascade属性

    Hibernate中的inverse和cascade属性 inverse的值有两种,"true"和"false".inverse="false&quo ...

  2. COGS 495. 窗口

    ★☆   输入文件:window.in   输出文件:window.out   简单对比时间限制:2 s   内存限制:256 MB [问题描述] 给你一个长度为N的数组,一个长为K的滑动的窗体从最左 ...

  3. 为什么ABAP整型的1转成string之后,后面会多个空格

    有同事问这个问题:lv_s是从int4转过来的,长度为2,和硬编码的lv_s2(长度为1)相比,后面多了个空格. 为什么?查SAP ABAP的编程帮助F1 help. 帮助文档说的很清楚了:如果赋值操 ...

  4. Chomp游戏(必胜策略分析)

    游戏简介 Chomp是一个双人游戏,有m x n块曲奇饼排成一个矩形格状,称作棋盘. ----两个玩家轮流自选一块还剩下的曲奇饼,而且还要把它右边和下边所有的曲奇饼都取走(如果存在) ----先吃到左 ...

  5. 【洛谷2019 OI春令营】期中考试

    T68402 扫雷 题目链接:传送门 题目描述 扫雷,是一款单人的计算机游戏.游戏目标是找出所有没有地雷的方格,完成游戏:要是按了有地雷的方格,游戏失败.现在 Bob 正在玩扫雷游戏,你作为裁判要判断 ...

  6. 最短路 || POJ 1847 Tram

    POJ 1847 最短路 每个点都有初始指向,问从起点到终点最少要改变多少次点的指向 *初始指向的那条边长度为0,其他的长度为1,表示要改变一次指向,然后最短路 =========高亮!!!===== ...

  7. python爬虫---从零开始(六)Selenium库

    什么是Selenium库: 自动化测试工具,支持多种浏览器.支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera ...

  8. 连接MySQL错误“plugin caching_sha2_password could not be loaded”的解决办法

    MySQL新版默认使用caching_sha2_password作为身份验证插件,而旧版是使用mysql_native_password.当连接MySQL时报错“plugin caching_sha2 ...

  9. jQuery闪烁提示,让新消息在网页标题显示

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head& ...

  10. scanf_s读取键盘输入字符串失败

    #include<stdio.h> int main() { ]; ]; printf("Input string:\n"); scanf_s("%s&quo ...