HDU-2586 How far away (最近公共祖先LCA+Trajan离线)

问题描述

村里有n栋房屋,还有一些双向道路连接起来。每天人们总是喜欢这样问:“如果我想从A房到B房,我能走多远?” 通常很难回答。但幸运的是,这个村庄的答案总是独一无二的,因为道路的建造方式是每两栋房屋之间有一条独特的简单路径(“简单”意味着你不能两次去一个地方)。Yout的任务是回答所有这些好奇的人。

输入

第一行是单个整数T(T <= 10),表示测试用例的数量。
  对于每个测试用例,在第一行中有两个数字n(2 <= n <= 40000)和m(1 <= m <= 200),房屋数量和查询数量。下面的n-1行每个包含三个数字i,j,k,分隔在一个空格中,这意味着有一条连接房屋i和房屋j的道路,长度为k(0 <k <= 40000)。房屋是标记为1到n。
  接下来m行每个都有不同的整数i和j,你可以回答房子i和房子j之间的距离。

产量

对于每个测试用例,输出m行。每行代表查询的答案。在每个测试用例后输出一条平淡的线。

样本输入

2

3 2

1 2 10

3 1 15

1 2

2 3

2 2

1 2 100

1 2

2 1

样本输出

10

25

100

100

dis[i]+dis[j]-2*dis[他们的公共祖先],就是要求的距离了

/*

*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <map>
#include <vector>
#include <set>
#include <bitset>
#include <stack>
#define ull unsigned long long
#define mems(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const double pi=acos(-1);
const int N=40004;
struct node
{
    int u,v,w,next;
} g[N*2];
struct nod
{
    int u,v,w,id,next;
} G[N*2];
int n,m,ans;
int head[N],hd[N];
int tot;
int res[N][4];
int dis[N];
int vis[N],pre[N],flag[N];
void init()
{
    tot=0;
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    memset(flag,0,sizeof(flag));
    memset(head,-1,sizeof(head));
    memset(hd,-1,sizeof(hd));
    memset(g,0,sizeof(g));
    memset(G,0,sizeof(G));
}
void addg(int u,int v,int w)
{
    g[tot].u=u;
    g[tot].v=v;
    g[tot].w=w;
    g[tot].next=head[u];
    head[u]=tot++;
}
void addG(int u,int v,int id)
{
    G[tot].u=u;
    G[tot].v=v;
//    G[tot].w=w;
    G[tot].id=id;
    G[tot].next=hd[u];
    hd[u]=tot++;
}
int Find(int x)
{
    if(x==pre[x])
        return x;
    else
        return pre[x]=Find(pre[x]);
}

void mix(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)
        pre[fy]=fx;
}
void Tarjan(int u)
{
    vis[u]=1;
    for(int i=head[u]; ~i; i=g[i].next)
    {
        int v=g[i].v;//查找其儿子节点
        if(!vis[v])//没有被访问过
        {
            dis[v]=dis[u]+g[i].w;//更新到根节点的距离
            Tarjan(v);//从根节点继续查
            mix(u,v);//把当前节点和它的父亲节点加入并查集
        }

    }
    for(int i=hd[u]; ~i; i=G[i].next)
    {
        int v=G[i].v;//找到当前询问的点
        if(vis[v])
        {//如果当前的点被标记过,那么他们的最近公共祖先就是find(v),然后计算出路径
            res[G[i].id][2]=Find(v);
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {

        scanf("%d%d",&n,&m);
        int a,b,c;
        init();
        for(int i=0; i<=n; i++)
        {
            pre[i]=i;
        }
        tot=0;
        for(int i=1; i<n; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            addg(a,b,c);
            addg(b,a,c);
        }
        tot=0;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d",&a,&b);
            addG(a,b,i);
            addG(b,a,i);
            res[i][0]=a;
            res[i][1]=b;
        }
        Tarjan(1);
//        Lca(1);
        for(int i=1; i<=m; i++)
        {
            printf("%d\n",dis[res[i][0]]+dis[res[i][1]]-2*dis[res[i][2]]);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`pd.merge()` 是 Pandas 库中用于合并数据的函数。它可以根据一个或多个键将不同的 DataFrame 对象合并在一起。 函数语法如下: ```python pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None) ``` 参数说明: - `left`:要合并的左侧 DataFrame。 - `right`:要合并的右侧 DataFrame。 - `how`:合并方式,可选值包括 `inner`(取交集)、`outer`(取并集)、`left`(以左侧 DataFrame 为准)、`right`(以右侧 DataFrame 为准)。 - `on`:要合并的列名,必须同时存在于左右两个 DataFrame 中。 - `left_on`:左侧 DataFrame 中用作合并键的列名。 - `right_on`:右侧 DataFrame 中用作合并键的列名。 - `left_index`:是否使用左侧 DataFrame 的索引作为合并键。 - `right_index`:是否使用右侧 DataFrame 的索引作为合并键。 - `sort`:是否按照合并键进行排序。 - `suffixes`:如果左右 DataFrame 存在相同的列名,用于指定列名后缀的元组。 - `copy`:是否在合并时复制数据。 - `indicator`:是否添加 `_merge` 列,用于指示合并方式。 - `validate`:是否检查合并键是否有效。 示例代码: ```python import pandas as pd # 创建两个 DataFrame df1 = pd.DataFrame({ 'key': ['A', 'B', 'C', 'D'], 'value': [1, 2, 3, 4] }) df2 = pd.DataFrame({ 'key': ['B', 'D', 'E', 'F'], 'value': [5, 6, 7, 8] }) # 根据 key 列进行内连接 df3 = pd.merge(df1, df2, on='key', how='inner') print(df3) ``` 输出结果: ``` key value_x value_y 0 B 2 5 1 D 4 6 ``` 在这个例子中,我们首先创建了两个 DataFrame,然后使用 `pd.merge()` 函数将它们根据 `key` 列进行内连接。由于 `key` 列中只有 `'B'` 和 `'D'` 这两个值同时存在于两个 DataFrame 中,因此最终合并的结果只包含这两行数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值