hdu2586 /// tarjan离线求树上两点的LCA

题目大意:

询问一棵树里 u 到 v 的距离

可由 dis[ u到根 ] + dis[ v到根 ] - 2*dis[ lca(u,v) ] 得到

https://blog.csdn.net/csyzcyj/article/details/10051173

#include <bits/stdc++.h>
#define mem(i,j) memset(i,j,sizeof(i))
using namespace std;

const int N=40005, Q=205;
struct EDGE { int to, w, nt; }e[N<<1], q[Q<<1];
int head[N], tot, que[N], pos;
// 题目数据可能有些问题 实际不止200个询问 WA了好多发 :(

int fa[N], dis[N], lca[Q];
bool vis[N];

int n, m, U[Q], V[Q];

void init() {
    tot=1; mem(head,0);
    pos=1; mem(que,0);
    mem(vis,0); mem(dis,0);
}
void addE(int u,int v,int w) {
    e[tot].to=v, e[tot].w=w;
    e[tot].nt=head[u];
    head[u]=tot++;
}
void addQ(int u,int v,int w) {
    q[pos].to=v, q[pos].w=w;
    q[pos].nt=que[u];
    que[u]=pos++;
}

int getfa(int u) {
    if(fa[u]==u) return u;
    return fa[u]=getfa(fa[u]);
}

void Tarjan(int u) {
    fa[u]=u; vis[u]=1;
    for(int i=head[u];i;i=e[i].nt) {
        int v=e[i].to;
        if(!vis[v]) {
            dis[v]=dis[u]+e[i].w;
            Tarjan(v); fa[v]=u;
        }
    }
    for(int i=que[u];i;i=q[i].nt) {
        int v=q[i].to;
        if(vis[v]) lca[q[i].w]=getfa(v);
    }
}

int main()
{
    int t; scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&m);
        init();

        for(int i=1;i<n;i++) {
            int u,v,w; scanf("%d%d%d",&u,&v,&w);
            addE(u,v,w); addE(v,u,w);
        }
        for(int i=1;i<=m;i++) {
            scanf("%d%d",&U[i],&V[i]);
            addQ(U[i],V[i],i), addQ(V[i],U[i],i);
        }

        Tarjan(1);
        for(int i=1;i<=m;i++)
            printf("%d\n",dis[U[i]]+dis[V[i]]-2*dis[lca[i]]);

    }

    return 0;
}

原文地址:https://www.cnblogs.com/zquzjx/p/10017833.html

时间: 2024-11-15 00:24:43

hdu2586 /// tarjan离线求树上两点的LCA的相关文章

F. Drivers Dissatisfaction+最小生成树+lca求树上两点的最大值

题目链接:F. Drivers Dissatisfaction 题意:n个点,m条边,每条边有一个w,代表这条路的不满意度,每一条边我们可以花费c来使不满意读-1:然后问你有s,找到一棵生成树是满意度最小 题解:对于s,我们可以知道花费在c最小的边上价值最优,我们可以先求一颗最小生成树,然后枚举没有用到的边,把连接这两点的最长边去掉判段能否更新最小值 这里求树上两点的最短路经过的最大值,我们可以有lca,或者树链抛分都可以 #include<bits/stdc++.h> #include<

Tarjan离线求LCA

Tarjan离线算法,相当于就是把整个树给DFS了一遍.DFS的同时,处理关于当前节点的询问.复杂度就是:O(n + q),n为总结点数,q为询问结点对数. 具体是怎么一回事呢. 看一下这个画个图理解一下就好了. //parent为并查集,FIND为并查集的查找操作 //QUERY为询问结点对集合 //TREE为基图有根树 Tarjan(u) visit[u] = true for each (u, v) in QUERY if visit[v] ans(u, v) = FIND(v) for

LCA(最近公共祖先)--tarjan离线算法 hdu 2586

HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11320    Accepted Submission(s): 4119 Problem Description There are n houses in the village and some bidirectional roads c

SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight. We will ask you to perform the following operation: u v k : ask for the kth minimum weight on the path from node u 

HDU 2586 How Far Away?(Tarjan离线算法求lca)

题意:给定一棵树n个节点m个询问,每次询问两个节点之间的距离. 思路:Tarjan离线算法求lca. 这题一开始交了n发一直爆栈.......百度了一下大概说的是这样hdu用的是windows服务器所以栈大小极其坑爹,稍微深一点的递归就会爆栈(正式比赛一般不会爆) 解决方法就是加一句#pragma comment(linker, "/STACK:1024000000,1024000000") 用c++交就好.....当然这只是针对比较坑爹oj来说的取巧的方法 #include<c

hdoj 2586 How far away ? 【Tarjan离线LCA】

题目:hdoj 2586 How far away ? 题意:给出一个有权树,求任意两点的之间的距离. 分析:思想就是以一个点 root 作为跟变成有根数,然后深搜处理处所有点到跟的距离.求要求的两个点的LCA(最近公共祖先), 然后ans = dis[x] + dis[y] - 2 * dis[LCA(x,y)],可以画图分析一下就知道. 求LCA我用的是Tarjan离线lca,由于询问次数很多,所以这个比较快. AC代码: #include <iostream> #include <

笔记:LCA最近公共祖先 Tarjan(离线)算法

LCA最近公共祖先 Tarjan他贱(离线)算法的基本思路及其算法实现 本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig/article/details/52336496 https://baike.baidu.com/item/最近公共祖先/8918834?fr=aladdin 最近公共祖先简称LCA(Lowest Common Ancesto

LCA之tarjan离线

显然81篇题解是有点多了,不让我提交. 更为不好的是没有一篇详细的\(tarjan\)(不过我也不会写详细的). 不过\(tarjan\)并没有我们想象的那样难理解,时间也并不爆炸(巧妙的跳过难写二字). 好了,下面说一说吧: \(LCA\)是什么该都知道吧(都翻到我博客了qwq) 度娘这样认为:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 直观的图: 呵呵,活跃下气氛. 图中3,5节点的\(LCA\)为2号节点,2,4节

[图论] LCA(最近公共祖先)Tarjan 离线算法

很好的参考资料:http://taop.marchtea.com/04.04.html    下面的配图和部分文字转载于此文章 离线算法就是指统一输入后再统一输出,而不是边输入边实时输出.Tarjan算法的复杂度为O(N+Q),Q为询问的次数. 由于是离线算法,所以要保存输入的信息,次序问题. 若两个结点u.v分别分布于某节点t 的左右子树,那么此节点 t即为u和v的最近公共祖先.更进一步,考虑到一个节点自己就是LCA的情况,得知: ?若某结点t 是两结点u.v的祖先之一,且这两结点并不分布于该