poj 1986 Distance Queries

简介: 点击打开链接poj 1986 思路:LCA+Tarjan离线算法+并查集 分析: 1 LCA指的是一棵有根树上两个点的最近公共祖先,或者指的是图上两个点的最短路径。 2 这一题的边数最大40000,还有k(k

点击打开链接poj 1986


思路:LCA+Tarjan离线算法+并查集

分析:
1 LCA指的是一棵有根树上两个点的最近公共祖先,或者指的是图上两个点的最短路径。
2 这一题的边数最大40000,还有k(k<=10000)次询问,如果利用最短路的算法肯定TLE。所以这个时候我们选择LCA,假设dis[x]是x到根节点的路径长度,那么(i , j)两点的最短路径为dis[i]+dis[j]-2*dis[LCA(i , j)];LCA(i , j)指的是i,j的最近公共祖先。
3 由于输入的是一个无向图,这个时候根节点是不固定的,所以保存的时候注意保存两次。然后只要随便选取一个作为根节点进行LCA即可(习惯把1作为根节点)
4 使用的是邻阶表存储无向图,注意数组的大小,不然会RE

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define MAXN 100010

int n , m , k;
int ancestor[MAXN];
int father[MAXN];
int first[MAXN];
int next[MAXN];
int dis[MAXN];
int vis[MAXN];/*标记点是否被处理过*/
vector<int>v[MAXN];
struct Edge{
   int x; 
   int y;
   int value;
   int ans;
}e[MAXN] , q[MAXN];/*保存读入的边和询问的边*/

/*初始化*/
void init(){
   for(int i = 1 ; i <= n ; i++){
      father[i] = i;
      v[i].clear();
   }
   memset(ancestor , 0 , sizeof(ancestor));
   memset(first , -1 , sizeof(first));
   memset(next , -1 , sizeof(next));
   memset(dis , 0 , sizeof(dis));
   memset(vis , 0 , sizeof(vis));
}

/*并查集的查找*/
int find_Set(int x){
   if(x != father[x])
     father[x] = find_Set(father[x]);
   return father[x];
}

/*并查集的合并*/
void union_Set(int x , int y){
    int root_x = find_Set(x);
    int root_y = find_Set(y);
    father[root_x] = root_y;
}

/*Tarjan算法*/
void LCA(int u){
    ancestor[u] = u;
    vis[u] = 1;/*标记为处理过*/
    for(int i = first[u] ; i != -1 ; i = next[i]){
       if(!vis[e[i].y]){/*找到没被处理过的点*/
           dis[e[i].y] = dis[u] + e[i].value;/*更新dis数组*/
           LCA(e[i].y);/*继续搜索子树*/
           union_Set(e[i].y , u);/*合并*/
           ancestor[find_Set(e[i].y)] = u;/*当前节点为子树的祖先*/
       }
    }
    /*处理和u 和 v[u][i]有关的询问*/
    for(int i = 0 ; i < v[u].size() ; i++){
       if(vis[v[u][i]]){
          for(int j = 0 ; j < k ; j++){
             if(q[j].x == u && q[j].y == v[u][i] || q[j].x == v[u][i] && q[j].y == u)
               q[j].ans = father[find_Set(v[u][i])];
          }
       }
    }
}

int main(){
    char c;
    while(scanf("%d%d" , &n , &m) != EOF){
        init();
        for(int i = 0 ; i < m ; i++){
           scanf("%d %d %d %c" , &e[i].x , &e[i].y , &e[i].value , &c);
           /*邻阶表存储无向图*/
           e[i+m].x = e[i].y;
           e[i+m].y = e[i].x;
           e[i+m].value = e[i].value;
        
           next[i] = first[e[i].x];
           first[e[i].x] = i;
           next[i+m] = first[e[i+m].x];
           first[e[i+m].x] = i+m;
        }
        scanf("%d" , &k);
        for(int i = 0 ; i < k ; i++){
           scanf("%d%d" , &q[i].x , &q[i].y);
           v[q[i].x].push_back(q[i].y);
           v[q[i].y].push_back(q[i].x);
        }
        LCA(1);/*1作为根节点求LCA*/
        for(int i = 0 ; i < k ; i++){
           int tmp = dis[q[i].x]+dis[q[i].y]-2*dis[q[i].ans];       
           printf("%d\n" , tmp);
        }
    }
    return 0;
}


目录
相关文章
|
SQL 缓存 Java
Mybatis面试题
Mybatis面试题
136 0
|
JSON API 数据格式
一行命令, 静态json变身api
作为一个前端开发者, 你可以会遇到没有测试数据的尴尬, 而这次我们用json-server, 优雅的解决这个问题 效果 关于 json-server json-server 全局安装方式: npm install -g json-server 使用方式: 如果有一个名为douyu.
1217 0
|
22小时前
|
云安全 人工智能 安全
AI被攻击怎么办?
阿里云提供 AI 全栈安全能力,其中对网络攻击的主动识别、智能阻断与快速响应构成其核心防线,依托原生安全防护为客户筑牢免疫屏障。
|
10天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
4天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
429 191
|
3天前
|
数据采集 消息中间件 人工智能
跨系统数据搬运的全方位解析,包括定义、痛点、技术、方法及智能体解决方案
跨系统数据搬运打通企业数据孤岛,实现CRM、ERP等系统高效互通。伴随数字化转型,全球市场规模超150亿美元,中国年增速达30%。本文详解其定义、痛点、技术原理、主流方法及智能体新范式,结合实在Agent等案例,揭示从数据割裂到智能流通的实践路径,助力企业降本增效,释放数据价值。
|
8天前
|
人工智能 自然语言处理 安全
国内主流Agent工具功能全维度对比:从技术内核到场景落地,一篇读懂所有选择
2024年全球AI Agent市场规模达52.9亿美元,预计2030年将增长至471亿美元,亚太地区增速领先。国内Agent工具呈现“百花齐放”格局,涵盖政务、金融、电商等多场景。本文深入解析实在智能实在Agent等主流产品,在技术架构、任务规划、多模态交互、工具集成等方面进行全维度对比,结合市场反馈与行业趋势,为企业及个人用户提供科学选型指南,助力高效落地AI智能体应用。