题目链接【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. 【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)

    [题意]给两个小写字母串A,B,请你计算: (1) A的一个最短的子串,它不是B的子串 (2) A的一个最短的子串,它不是B的子序列 (3) A的一个最短的子序列,它不是B的子串 (4) A的一个最短 ...

  2. 当月第一天、最后一天、下月第一天,时间date

    时间记录,不是时间戳 $thismonth = date('m'); $thisyear = date('Y'); $startDay = $thisyear . '-' . $thismonth . ...

  3. 【洛谷 P3690】 【模板】Link Cut Tree (动态树)

    题目链接 \(RT\). FlashHu巨佬的博客 #include <cstdio> #define R register int #define I inline void #defi ...

  4. 【leetcode 简单】第四十二题 阶乘后的零

    给定一个整数 n,返回 n! 结果尾数中零的数量. 示例 1: 输入: 3 输出: 0 解释: 3! = 6, 尾数中没有零. 示例 2: 输入: 5 输出: 1 解释: 5! = 120, 尾数中有 ...

  5. virtualenv搭建虚拟环境

    最近因为项目需要,要在CentOS 7 上搭建一套开发环境,虽说Python的背后有着庞大的开源社区支持,但是有一个缺点就是每个包的质量都参差不齐,如果我们在工作服务器上去测试安装每个包,就会造成整个 ...

  6. Thinkphp的自定义路由(route.php)

    废话:因为thinkphp的默认路由会导致URL特别长,从而会影响搜索引擎优化.所以就衍生了自定义路由,尽量将URL缩短. 这是默认的路由文件: <?php return [ '__patter ...

  7. 【swupdate文档 五】从可信的来源更新镜像

    从可信的来源更新镜像 现在越来越重要的是,设备不仅要能安全地进行更新操作, 而且要能够验证发送的图像是否来自一个已知的源, 并且没有嵌入恶意软件. 为了实现这个目标,SWUpdate必须验证传入的镜像 ...

  8. openjudge-NOI 2.6-2985 数字组合

    题目链接:http://noi.openjudge.cn/ch0206/2985/ 题解: 跟背包问题有点相似,暂且算背包型DP吧,虽然是一道递推题…… fj表示和为j时的结果,得: 即为j减去每一个 ...

  9. ftp,nfs和samba的区别

    先从名字上进行理解: 1. FTP(文件传输协议) 2. NFS(网络文件系统) 3. samba 即smb(服务信息块)协议 1 其中FTP 是TCP/IP协议栈所提供的一种子协议,该子协议具体可以 ...

  10. 洛谷 P2369 EXCEEDED WARNING A 题解

    题目传送门 直接用sort排序最后输出即可.但是数组要使用short int 类型.否则会超内存. #include<bits/stdc++.h> using namespace std; ...