题目链接【https://vjudge.net/problem/HDU-2874】

题意: 输入一个森林,总节点不超过N(N<10000),由C次询问(C<1000000),每次询问两个点,如果来联通输出,两点之间的距离,如果不来联通,输出“Not connected”;

思路:首先判断u,v两个点在不在同一个树上,用并查集来做,如果在,就求两者的LCA,输入距离dis[u->v]=dis[u]+dis[v]-2*dis[LCA(u,v)]。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = ;
int N, M, C;
struct node
{
int id, next, len;
} E[maxn << ];
int head[maxn << ], num;
void initlist()
{
memset(head, -, sizeof(head));
num = ;
}
void adde(int u, int v, int len)
{
E[num].id = u;
E[num].len = len;
E[num].next = head[v];
head[v] = num++;
}
//----------------------------------------邻接表
int fa[maxn<<];
void initfa()
{
for(int i = ; i <= N; i++)
fa[i] = i;
}
int Find(int id)
{
if(id == fa[id]) return id;
else return fa[id] = Find(fa[id]);
}
void addu(int u, int v)
{
int x = Find(u);
int y = Find(v);
if(x != y) fa[x] = y;
}
//----------------------------------------并查集
int p[][maxn], dep[maxn], dis[maxn], vis[maxn];
void DFS(int u, int FA)
{
vis[u] = ;
for(int l = head[u]; l != -; l = E[l].next)
{
int id = E[l].id;
if(id == FA||vis[id]) continue;
dep[id] = dep[u] + ;
dis[id] = dis[u] + E[l].len;
p[][id] = u;
DFS(id, u);
}
}
void initlca()
{
memset(p, -, sizeof(p));
memset(dep,,sizeof(dep));
memset(dis, , sizeof(dis));
memset(vis, , sizeof(vis));
for(int i = ; i <= N; i++)
{
if(!vis[i])
DFS(i, -);
}
for(int k = ; k + <= ; k++)
for(int u = ; u <= N; u++)
{
if(p[k][u] < ) p[k + ][u] = -;
else
p[k + ][u] = p[k][p[k][u]];
}
}
int LCA(int u, int v)
{
if(dep[u] > dep[v]) swap(u, v);
for(int k = ; k <= ; k++)
{
if((dep[v] - dep[u]) >> k & )
v = p[k][v];
}
if(u == v) return u;
for(int k = ; k >= ; k--)
{
if(p[k][u] != p[k][v])
{
u = p[k][u];
v = p[k][v];
}
}
return p[][u];
}
//----------------------------------------LCA
int main ()
{
while(~scanf("%d%d%d", &N, &M, &C))
{
initlist();
initfa();
int u, v, ds;
for(int i = ; i <= M; i++)
{
scanf("%d%d%d", &u, &v, &ds);
adde(u, v, ds);
adde(v, u, ds);
addu(u, v);
}
initlca();
for(int i=;i<=C;i++)
{
scanf("%d%d",&u,&v);
int x=Find(u);
int y=Find(v);
if(x==y)
{
printf("%d\n",dis[u]+dis[v]-*dis[LCA(u,v)]);
}
else
printf("Not connected\n");
}
}
return ;
}
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = ;
//---------------------------------//邻接表
struct node
{
int to, len, next;
} E[MAXN * ];
int p[MAXN * ], tot;
void init()
{
memset(p, -, sizeof(p));
tot = ;
}
void add(int u, int v, int len)
{
E[tot].to = v;
E[tot].len = len;
E[tot].next = p[u];
p[u] = tot++;
}
//---------------------------------//并查集
int fa[MAXN * ];
void init2(int n)
{
for(int i = ; i <= n; i++)
fa[i] = i;
}
int Find(int x)
{
if(x == fa[x])
return fa[x];
else
return fa[x] = Find(fa[x]);
}
void join (int i, int j)
{
int x = Find(i);
int y = Find(j);
if(x != y) fa[y] = x;
}
//----------------------------------//LAC
int ver[MAXN * ], vis[MAXN], fst[MAXN], R[MAXN * ];
int dis[MAXN], KT[MAXN * ], dp[MAXN * ][];
void init3()
{
memset(vis, , sizeof(vis));
tot = ;
}
void DFS(int u, int dep, int len)
{
vis[u] = ;
ver[++tot] = u;
R[tot] = dep;
fst[u] = tot;
dis[u] = len;
for(int k = p[u]; k != -; k = E[k].next)
{
int v = E[k].to;
if(vis[v]) continue;
DFS(v, dep + , len + E[k].len);
ver[++tot] = u;
R[tot] = dep;
}
}
void ST(int n)
{
KT[] = ;
for(int i = ; i <= n; i++)
KT[i] = KT[i / ] + ;
for(int i = ; i <= n; i++)
dp[i][] = i;
for(int j = ; j <= KT[n]; j++)
for(int i = ; i + ( << j) - <= n; i++)
{
int x = dp[i][j - ];
int y = dp[i + ( << (j - ))][j - ];
dp[i][j] = R[x] < R[y] ? x : y;
}
}
int RMQ(int l, int r)
{
int k = KT[r - l + ];
int x = dp[l][k];
int y = dp[r - ( << k) + ][k];
return R[x] < R[y] ? x : y;
}
int LCA(int u, int v)
{
int l = fst[u], r = fst[v];
if(l > r) swap(l, r);
int t = RMQ(l, r);
return ver[t];
}
//-------------------------------------//主函数
int N, M, C;
int main ()
{
while(~scanf("%d%d%d", &N, &M, &C))
{
init();//
init2(N);
int u, v, len;
for(int i = ; i <= M; i++)
{
scanf("%d%d%d", &u, &v, &len);
add(u, v, len);
add(v, u, len);
join(u, v);
}
init3();
for(int i = ; i <= N; i++)
{
if(vis[i]) continue;
DFS(i, , );
}
ST( * N - );
for(int i = ; i <= C; i++)
{
scanf("%d%d", &u, &v);
int x = Find(u);
int y = Find(v);
if(x != y)
{
printf("Not connected\n");
continue;
}
int lca = LCA(u, v);
printf("%d\n", dis[u] + dis[v] - * dis[lca]);
}
}
return ;
}

HDU2874【倍增、ST】的更多相关文章

  1. caioj 1237: 【最近公共祖先】树上任意两点的距离 在线倍增ST

    caioj 1237: [最近公共祖先]树上任意两点的距离 倍增ST 题目链接:http://caioj.cn/problem.php?id=1237 思路: 针对询问次数多的时候,采取倍增求取LCA ...

  2. 浅谈 倍增/ST表

    命题描述 给定一个长度为 \(n\) 的序列,\(m\) 次询问区间最大值 分析 上面的问题肯定可以暴力对吧. 但暴力肯定不是最优对吧,所以我们直接就不考虑了... 于是引入:倍增 首先,倍增是个什么 ...

  3. P7599-[APIO2021]雨林跳跃【二分,倍增,ST表】

    正题 题目链接:https://www.luogu.com.cn/problem/P7599 题目大意 \(n\)棵树,在某棵树上时可以选择向左右两边第一棵比它高的树跳,现在\(q\)次询问从\([A ...

  4. poj 3264 倍增 ST表

    #include<iostream> #include<cmath> using namespace std; ; int a[maxn]; ]; ]; int quick(i ...

  5. 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)

    [HAOI2007]理想的正方形 题目描述 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: ...

  6. poj3264Balanced Lineup(倍增ST表)

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 52328   Accepted: 24551 ...

  7. 倍增ST应用 选择客栈(提高组)

    重磅例题!ST表应用!提高组Getting! 1125: B15-倍增-习题:选择客栈[ST表应用] 时间限制: 1 Sec  内存限制: 128 MB提交: 35  解决: 12[提交] [状态] ...

  8. Problem 1016 咒文卷轴 优先队列+前缀和+rmq

    题目链接: 题目 Problem 1016 咒文卷轴 Time Limit: 3000 mSec Memory Limit : 131072 KB 问题描述 小Y 是一个魔法师,有一天他获得了一卷神秘 ...

  9. bzoj2342

    shoi题目好坑爹 首先自己测发现这道题如果用后缀数组+rmq处理每个点回文串能延伸长度的话会TLE (当然我用的是倍增+ST的方法,如果用三分构建后缀数组+笛卡尔树处理rmq我就不知道了): 关于最 ...

  10. 【解题报告】Math

    = =本来昨天就该发的,只是断网……. MATH  [题目描述] 小 x正在做他的数学作业,可是作业实在太难了.题目是这样的: 1.给定一个含有N个数的数列 V. 2.你可以从数列中恰好移除 K个数, ...

随机推荐

  1. Disruptor的使用

    ..................2015年的第一天................... 本文代码托管在 https://github.com/hupengcool/disruptor-start ...

  2. Freemarker代码生成器原理说明

    一.Freemarker基本原理: FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用 ...

  3. BestCoder Round92

    题目链接:传送门 HDU 6015-6018 解题报告:传送门 HDU6015 Skip the Class  Accepts: 678  Submissions: 1285  Time Limit: ...

  4. 【总结】对FFT的理解 / 【洛谷 P3803】 【模板】多项式乘法(FFT)

    题目链接 \(\Huge\text{无图,慎入}\) \(FFT\)即快速傅里叶变换,用于加速多项式乘法. 如果暴力做卷积的话就是一个多项式的每个单项式去乘另一个多项式然后加起来,时间复杂度为\(O( ...

  5. HDU 2516 取石子游戏 (找规律)

    题目链接 Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍.取完者胜.先取者负输出" ...

  6. dataTables.js 响应式/package-lock.json 作用/eclipse 目录和工作区建立连接/navcat 导出数据库/vscode 快速进入方法

    下班时间到啦! --下班都是他们的,而我,什么都没有. 什么周五放松日,什么五四青年节,什么都么有.继续总结一下今天遇到的问题. dataTables.js 响应式 使用dataTables.js创建 ...

  7. react 修改state某一属性值

    1.state // 筛选框相关数据 searchSelect: { term: { value: '学期', key: '', options: [] }, type_of_personnel: { ...

  8. WordPress404页面自定义

    不知道大家是怎么设计404页面,个性的404可以为网站增色不少,wordpress设置404是在主题里面的404.php页面上,当然比如你用Apache.nginx等服务器,你可以自己建一个单页,内容 ...

  9. Python3 反射及常用的方法

    反射就是通过字符串映射或修改程序运行时的状态.属性.方法 有四个常用方法: hasattr(obj,name_str) 判断一个obj对象是否有对应name_str的方法 getattr(obj,na ...

  10. Ubuntu之设置应用开机自启动

    前言 前面使用oricle-Linux的时候,设置开机自启动使用的是chkconfig,现在使用ubuntu的时候发现Ubuntu系统没有了RH系统中的 chkconfig命令,因此研究了一下ubun ...