HDU 2874 LCA离线算法 tarjan算法

给出N个点,M条边,Q次询问

Q次询问每两点之间的最短距离

典型LCA 问题   Marjan算法解

#include "stdio.h"
#include "string.h"

struct Edge
{
    int to,next,len;
}edge[20010];

struct Ques
{
    int to,next,index;
}ques[2000010];
int head[10010],q_head[10010],f[10010],dis[10010];

int vis[10010],ans[1000010];
// vis记录结点是否被遍历过,并且存储结点所在的树是哪颗
// ans记录每个询问的答案
int n,m,q,tot,q_tot;

void add_edge(int a,int b,int c)
{
    edge[tot].to=b;
    edge[tot].next=head[a];
    edge[tot].len=c;
    head[a]=tot++;

    edge[tot].to=a;
    edge[tot].next=head[b];
    edge[tot].len=c;
    head[b]=tot++;
}

void add_ques(int a,int b,int index)
{
    ques[q_tot].to=b;
    ques[q_tot].next=q_head[a];
    ques[q_tot].index=index;
    q_head[a]=q_tot++;

    ques[q_tot].to=a;
    ques[q_tot].next=q_head[b];
    ques[q_tot].index=index;
    q_head[b]=q_tot++;
}

int find(int w)
{
    if (f[w]==w) return w;
    return f[w]=find(f[w]);
}

void Tarjan(int w,int deep,int root) // w:当前点,deep:当前深度,root:根节点
{
    int i,v;
    f[w]=w;
    vis[w]=root;
    dis[w]=deep;

    for (i=q_head[w];i!=-1;i=ques[i].next)
    {
        v=ques[i].to;
        if (vis[v]==root)
            ans[ques[i].index]=dis[v]+dis[w]-2*dis[find(v)];
    }

    for (i=head[w];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        if (vis[v]==-1)
        {
            Tarjan(v,deep+edge[i].len,root);
            f[v]=w;
        }
    }
}
void init()
{
    int i,a,b,c;
    memset(head,-1,sizeof(head));
    memset(q_head,-1,sizeof(q_head));
    tot=q_tot=0;

    while (m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        add_edge(a,b,c);
    }

    for (i=1;i<=q;i++)
    {
        scanf("%d%d",&a,&b);
        add_ques(a,b,i);
    }
    memset(vis,-1,sizeof(vis));
    memset(ans,-1,sizeof(ans));
}
int main()
{
    int i;
    while (scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        init();
        for (i=1;i<=n;i++)
            if (vis[i]==-1)
                Tarjan(i,0,i);

        for (i=1;i<=q;i++)
            if (ans[i]==-1)
                printf("Not connected\n");
            else
                printf("%d\n",ans[i]);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 03:53:45

HDU 2874 LCA离线算法 tarjan算法的相关文章

HDU 2874 LCA离线算法

Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4477    Accepted Submission(s): 1284 Problem Description After World War X, a lot of cities have been seriously damage

hdu 1269 迷宫城堡 (tarjan算法学习)

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7056    Accepted Submission(s): 3137 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A

HDU 2586 LCA离线算法 tarjan算法

LCA tarjan算法模板题 题意:给一个无根树,有q个询问,每个询问两个点,问两点的距离. 用tarjan离线算法算出每个询问的两点的最近公共祖先 ans[i]=dis[x[i]]+dis[y[i]]-2*dis[z[i]]; //  x[i],y[i]分别存储每次询问的两点,z[i]存储这两点的最近公共祖先 #include "stdio.h" #include "string.h" int tot,n,m; int f[40010],x[40010],y[4

(转载)LCA问题的Tarjan算法

转载自:Click Here LCA问题(Lowest Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两个顶点u和v的最近公共祖先,即找一个节点,同时是u和v的祖先,并且深度尽可能大(尽可能远离树根).LCA问题有很多解法:线段树.Tarjan算法.跳表.RMQ与LCA互相转化等.本文主要讲解Tarjan算法的原理及详细实现. 一 LCA问题 LCA问题的一般形式:给定一棵有根树,给出若干个查询,每个

有向图的强连通算法 -- tarjan算法

(绘图什么真辛苦) 强连通分量: 在有向图 G 中.若两个顶点相互可达,则称两个顶点强连通(strongly connected). 假设有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图.称为强连通分量(strongly connected components). 比方上面这幅图( a, b, e ), ( d, c, h ), ( f, g ) 分别为三个 SCC. tarjan算法伪代码: 该算法由 Robert Tarjan 发明,原论文:Tarjan1

Hdu 2874(LCA)

题目链接 Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5037    Accepted Submission(s): 1399 Problem Description After World War X, a lot of cities have been seriously d

HDU 2874 LCA转RMQ+并查集

点击打开链接 题意:问两个城市是否相连,不相连输出Not connected,否则输出两个城市间的最短距离 思路:用并查集判断两个城市的连通性,如果联通则做法和LCA一样,但是注意的一点是地图不连通的话,我们要将所有点都建起来,就要加一个模拟的点,将所有图串起来,很好处理的,看一下就会了 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include

HDU 2586 How far away ? (离线LCA Tarjan算法模板)

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

【POJ 1330 Nearest Common Ancestors】LCA Tarjan算法

题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从树根出发进行后序深度优先遍历,设置vis数组实时记录是否已被访问. 每遍历完一棵子树r,把它并入以r的父节点p为代表元的集合.这时判断p是不是所要求的u, v节点之一,如果r==u,且v已访问过,则lca(u, v)必为v所属集合的代表元.p==v的情况类似. 我的第一道LCA问题的Tarjan算法