首页 > 编程语言 >AcWing 1171. 距离 Tarjan算法离线求LCA

AcWing 1171. 距离 Tarjan算法离线求LCA

时间:2024-03-18 22:31:31浏览次数:29  
标签:Tarjan include dist 1171 idx int 离线 st 左下

题目

输入样例1:

2 2 
1 2 100 
1 2 
2 1

输出样例1: 

100
100

输入样例2:

3 2
1 2 10
3 1 15
1 2
3 2

输出样例2: 

10
25

LCA算法:

LCA(Least Common Ancestors)最近公共祖先

Tarjan 求 LCA 是一种离线的算法,也就是说它一遍求出所有需要求的点的 LCA,而不是需要求哪两个点再去求。

在深度优先遍历时,将所有点分成三大类:

[1]已经遍历过,且回溯过的点

[2]正在搜索的分支

[3]还未搜索到的点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

#define x first
#define y second

using namespace std;

typedef pair<int,int> PII;
const int N = 10010,M = 2*N;
int n,m;
int h[N],e[M],w[M],ne[M],idx;//邻接表
int dist[N];//每个点和1号点的距离
int p[N];//并查集
int res[M];//存储答案
int st[N];//存储每个节点的状态
vector<PII> query[N];//存储每组询问
// query[i][first][second] 
//first存查询距离i的另外一个点j,second存查询编号idx

void add(int a,int b,int c)
{
    e[idx]=b;
    ne[idx]=h[a];
    w[idx]=c;
    h[a]=idx++;
}

int find(int x)
{
    if(p[x]!=x)
        p[x]=find(p[x]);
    return p[x];
}

void dfs(int u,int fa)
{
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j==fa)
            continue;
        dist[j]=dist[u]+w[i];
        dfs(j,u);
    }
}

//st[u]==2已经遍历并且回溯了
//st[u]==1正在遍历
void tarjan(int u)
{
    st[u]=1;//当前路径点标记为1
    // u这条路上的根节点的左下的点用并查集合并到根节点
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(!st[j])
        {
            tarjan(j);//往左下搜
            p[j]=u;//从左下回溯后把左下的点合并到根节点
        }
    }
    
    // 对于当前点u 搜索所有和u
    for(auto item:query[u])
    {
        int y=item.first,id=item.second;
        
        if(st[y]==2)//如果查询的这个点已经是左下的点
        {           //(已经搜索过且回溯过,标记为2)
            int anc=find(y);//y的根节点
            //y节点的p[y]已经回溯到公共祖先
            // x到y的距离 = d[x]+d[y] - 2*d[lca]
            res[id]=dist[u]+dist[y]-2*dist[anc];
            //第idx次查询的结果 res[idx]
        }
    }
    //点u已经搜索完且要回溯了 就把st[u]标记为2
    st[u]=2;
}
int main()
{
    cin>>n>>m;
    // 建图
    memset(h, -1, sizeof h);
    
    for(int i=0;i<n-1;i++)
    {
        int x,y,k;
        scanf("%d%d%d",&x,&y,&k);
        add(x,y,k);
        add(y,x,k);
    }
    
    // 存下询问
    for(int i=0;i<m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(x!=y)
        {
            query[x].push_back({y,i});
            query[y].push_back({x,i});
        }
    }
    
    for(int i=1;i<=n;i++)
        p[i]=i;
    
    dfs(1,-1);
    tarjan(1);
    
    for(int i=0;i<m;i++)
        printf("%d\n",res[i]);//把每次询问的答案输出
        
    return 0;
}

标签:Tarjan,include,dist,1171,idx,int,离线,st,左下
From: https://blog.csdn.net/m0_73043916/article/details/136824042

相关文章

  • 离线数仓建设之数据导出
    为了方便报表应用使用数据,需将ADS各项指标统计结果导出到MySQL,方便熟悉SQL人员使用。1MySQL建库建表1.1创建数据库创建car_data_report数据库:CREATEDATABASEIFNOTEXISTScar_data_report#字符集DEFAULTCHARSETutf8mb4#排序规则COLLATEutf8mb4_general_ci;1......
  • Tarjan整理
    求强连通分量个数#include<iostream>#include<cstdio>#include<stack>usingnamespacestd;structsss{ intt,ne;}e[1000005];inth[1000005],cnt;voidadd(intu,intv){ e[++cnt].ne=h[u]; e[cnt].t=v; h[u]=cnt;}intdfn[1000005],......
  • tarjan模板
    信息传递题目描述tarjan模板点击查看代码voidtarjan(intx){ dfn[x]=low[x]=++num; stk.push(x); v[x]=1; for(inti=h[x];i;i=nxt[i]) { if(!dfn[to[i]]) { tarjan(to[i]); low[x]=min(low[x],low[to[i]]); } elseif(v[to[i]]) { low[x]=min(lo......
  • webScoket离线消息暂存,上线发送
    webScoket离线消息暂存,上线发送用webScoket的即时聊天通讯,功能可群发单发,可对不在线用户发送消息时用户一上线立马就能收到消息,也可以查看未读数量导入依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</arti......
  • salt-minion离线安装
    1.在nexus做salt官方的yum源代理http://xxxx/repository/gw-yum-proxys代理https://repo.saltproject.io/salt/py3/2.在yum仓库里上传repo文件及salt.sh安装文件latest.repo 文件[salt-repo]name=SaltrepoforRHEL/CentOS7PY3baseurl=http://xxxx/repository/gw-yum-......
  • python(pip)包/模块:如何离线安装?
    1、生成requirements.txt文件如果有同环境服务器,可直接生成requirements.txt,会把当前服务器下的包和版本写入文件中。pipfreeze>requirements.txt如安装指定包,创建requirements.txt,输入包名==版本号//只输入包名,默认最新版本。例:xlwt==1.3.02、下载包在requirements.t......
  • element ui 中文离线文档(百度云盘下载)
    一般内网开发上不了网,用离线版本比较方便,下载地址:https://download.csdn.net/download/li836779537/88355878?spm=1001.2014.3001.5503下载后里面有个index.hrml双击打开就可以用效果如下:......
  • tarjan 各类板子集合
    tarjan大板子(非讲解):1、普通缩点DGAvoidtarjan(intx){ dfn[x]=low[x]=++cntp; q.push(x);v[x]=1; for(inti=head[x];i;i=bi[i].next){ intj=bi[i].to; if(!dfn[j]){ tarjan(j); low[x]=min(low[x],low[j]); } elseif(v[j])low[x]=min(low[x],dfn[j]); }......
  • tarjan模板
    因ppt太水遂有此文有向图求强连通分量点击查看代码voidtarjan(intx){ dfn[x]=low[x]=++num; stk.push(x); f[x]=1; for(inti=head[x];i;i=net[i]) { if(!dfn[to[i]]) { tarjan(to[i]); low[x]=min(low[x],low[to[i]]); } elseif(f[to[i]]) { l......
  • tarjan
    缩点有向图缩点(把一个强连通分量看成一个点),用于优化。树枝边:DFS时经过的边,即DFS搜索树上的边反祖边:也叫回边或后向边,与DFS方向相反,从某个结点指向其某个祖先的边横叉边:从某个结点指向搜索树中另一子树中的某结点的边,它主要是在搜索的时候遇到了一个已经访问过的结点,但......