ZOJ Problem Set - 3195 Design the city 【Tarjan离线LCA】

题目:ZOJ Problem Set - 3195 Design the city

题意:给出一个图,求三点的连起来的距离。

分析:分别求出三点中任意两点的距离 / 2  = ans

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define N 50010
#define M 20010

struct Node
{
    int to,val;
};
vector<Node> g[N];
struct ask{
    int u,v,lca;
};
vector<ask> e;
vector<int> query[N];
int fa[N],ance[N],dir[N];
bool vis[N];

inline void add_Node(int u ,int v,int w)
{
    g[u].push_back((Node){v,w});
    g[v].push_back((Node){u,w});
}

inline void add_ask(int u ,int v )
{
    e.push_back((ask){u,v,-1});
    e.push_back((ask){v,u,-1});
    int len = e.size()-1;
    query[v].push_back(len);
    query[u].push_back(len-1);
}

int find(int x){
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void Tarjan(int u,int val)
{
    vis[u] = true;
    ance[u] = fa[u] = u;
    dir[u] = val;
    for(int i=0;i<g[u].size();i++)
    {
        Node tmp = g[u][i];
        if(!vis[tmp.to])
        {
            Tarjan(tmp.to,val+tmp.val);
            fa[tmp.to] = u;
        }
    }
    for(int i=0;i<query[u].size();i++)
    {
        int num = query[u][i];
        ask& tmp = e[num];
        if(vis[tmp.v])
        {
            tmp.lca = e[num^1].lca = ance[find(tmp.v)];
        }
    }
}
void Clear(int n)
{
    memset(vis,false,sizeof(vis));
    for(int i=0;i<=n;i++){
        g[i].clear();
        query[i].clear();
    }
    e.clear();
}
int main()
{
    //freopen("Input.txt","r",stdin);
    int n,m,fack = 0;
    while(~scanf("%d",&n))
    {
        Clear(n);
        for(int i=1;i<n;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add_Node(x,y,z);
        }
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add_ask(x,y);
            add_ask(x,z);
            add_ask(y,z);
        }
        Tarjan(0,0);
        int ans = 0;
        if(fack)
            puts("");
        fack = 1;
        for(int i=0;i<3*m;i++)
        {
            ans+=( dir[e[i*2].u] + dir[e[i*2].v] - 2*dir[e[i*2].lca] );
            if(i%3==2){
                printf("%d\n",ans/2);
                ans = 0;
            }
        }
    }
    return 0;
}
时间: 2024-08-09 23:52:35

ZOJ Problem Set - 3195 Design the city 【Tarjan离线LCA】的相关文章

ZOJ 3195 Design the city

倍增法在线LCA..... ZOJ Problem Set - 3195 Design the city Time Limit: 1 Second      Memory Limit: 32768 KB Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terrible, that there are traffic jams everywhere. Now,

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 <

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 

ZOJ 3195 Design the city LCA

题目:http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3195 题意:给定一个树,求三点之间的距离 思路:假定三点为u, v, w,那么(dist[u,v] + dist[v,w] + dist[u,w]) / 2就是答案 总结:wa时不要灰心,也许你离ac不远了 #include<iostream> #include<cstdio> #include<cstring> #include<alg

ZOJ 3195 Design the city 题解

这个题目大意是: 有N个城市,编号为0~N-1,给定N-1条无向带权边,Q个询问,每个询问求三个城市连起来的最小权值. 多组数据 每组数据  1 < N < 50000  1 < Q < 70000: 一道多源最短路的题目,注意题目数据:N.Q都很大 不能考虑Floyd.SPFA.Dijkstra.Bellman-Ford等最短路算法 再看N-1条边,明显构成一棵树,最短路有且只有一条 很明显需要LCA.... 不懂LCA的点!我!点!我! 我们所熟知的LCA是求两个点的最短路,而

ZOJ 3195 Design the city(LCA变形)

题意:给定一棵树,求连接三点所需的最短距离. 思路:LCA变形,连接三点的最短距离可以转化为求任意两点距离之和的和再除以二. #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #incl

zoj 3195 Design the city lca倍增

题目链接 给一棵树, m个询问, 每个询问给出3个点, 求这三个点之间的最短距离. 其实就是两两之间的最短距离加起来除2. 倍增的lca模板 #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <s

poj 1470 Closest Common Ancestors 【Tarjan 离线 LCA】

题目:poj 1470 Closest Common Ancestors 题意:给出一个树,一些询问.求LCA的个数. 分析:很简单的模板题目,但是模板不够优秀,一直wa...RE,各种错误一下午,终于发现自己模板的漏洞了. AC代码: #include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; #define N 1010 #

hdu 2586 How far away ?(Tarjan离线LCA)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:对于一个有 n 个节点的图,有 n - 1 条无向边,权值给出.有 m 个查询, 每个查询 a b 表示询问 a b 两节点间的距离. 思路: 把这个联通图以树的形式表现出来,取任意两点,假设其最近公共祖先(Least Common Ancestors)为 lca,则两点间的距离等于: dis(a, b) = dis(a, root) + dis(b, root) - 2 * dis(r