HDU2874【倍增、ST】
题目链接【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】的更多相关文章
- caioj 1237: 【最近公共祖先】树上任意两点的距离 在线倍增ST
caioj 1237: [最近公共祖先]树上任意两点的距离 倍增ST 题目链接:http://caioj.cn/problem.php?id=1237 思路: 针对询问次数多的时候,采取倍增求取LCA ...
- 浅谈 倍增/ST表
命题描述 给定一个长度为 \(n\) 的序列,\(m\) 次询问区间最大值 分析 上面的问题肯定可以暴力对吧. 但暴力肯定不是最优对吧,所以我们直接就不考虑了... 于是引入:倍增 首先,倍增是个什么 ...
- P7599-[APIO2021]雨林跳跃【二分,倍增,ST表】
正题 题目链接:https://www.luogu.com.cn/problem/P7599 题目大意 \(n\)棵树,在某棵树上时可以选择向左右两边第一棵比它高的树跳,现在\(q\)次询问从\([A ...
- poj 3264 倍增 ST表
#include<iostream> #include<cmath> using namespace std; ; int a[maxn]; ]; ]; int quick(i ...
- 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)
[HAOI2007]理想的正方形 题目描述 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: ...
- poj3264Balanced Lineup(倍增ST表)
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 52328 Accepted: 24551 ...
- 倍增ST应用 选择客栈(提高组)
重磅例题!ST表应用!提高组Getting! 1125: B15-倍增-习题:选择客栈[ST表应用] 时间限制: 1 Sec 内存限制: 128 MB提交: 35 解决: 12[提交] [状态] ...
- Problem 1016 咒文卷轴 优先队列+前缀和+rmq
题目链接: 题目 Problem 1016 咒文卷轴 Time Limit: 3000 mSec Memory Limit : 131072 KB 问题描述 小Y 是一个魔法师,有一天他获得了一卷神秘 ...
- bzoj2342
shoi题目好坑爹 首先自己测发现这道题如果用后缀数组+rmq处理每个点回文串能延伸长度的话会TLE (当然我用的是倍增+ST的方法,如果用三分构建后缀数组+笛卡尔树处理rmq我就不知道了): 关于最 ...
- 【解题报告】Math
= =本来昨天就该发的,只是断网……. MATH [题目描述] 小 x正在做他的数学作业,可是作业实在太难了.题目是这样的: 1.给定一个含有N个数的数列 V. 2.你可以从数列中恰好移除 K个数, ...
随机推荐
- 成为优秀 Node.js 程序员的10个习惯
JavaScript出现近二十年了,但由于其有些问题不能解决,使得像Python和Ruby这一类的语言很吸引人,这些问题包括命令行接口.交互式开发环境.包的管理和没有一个有组织开源社区等.幸亏Node ...
- LintCode 156: Merge Interval
LintCode 156: Merge Interval 题目描述 给出若干闭合区间,合并所有重叠的部分. 样例 给出的区间列表 => 合并后的区间列表: [ [ [1, 3], [1, 6], ...
- 【BZOJ】2125: 最短路 圆方树(静态仙人掌)
[题意]给定带边权仙人掌图,Q次询问两点间最短距离.n,m,Q<=10000 [算法]圆方树处理仙人掌问题 [题解]树上的两点间最短路问题,常用倍增求LCA解决,考虑扩展到仙人掌图. 先对仙人掌 ...
- c++ virtual总结
virtual-关键字用于修饰成员函数时,有以下特性 1.用于修饰的基类的成员函数,被修饰的基类成员函数-其派生类的同名成员函数也默认带有virtual 关键字2.当virtual 用于修饰析构函数( ...
- CodeForces 869B
Even if the world is full of counterfeits, I still regard it as wonderful. Pile up herbs and incense ...
- VueJS 集成 medium editor 自定义编辑器按钮
详见我的新博客: 守望之吻
- bugku数字验证绕过正则
题目:http://120.24.86.145:9009/21.php 第6行使用正则匹配如果匹配到$password开头12个字符中有空格则输出flag并执行exit; 12行是正则匹配$passw ...
- 33 - 并发编程-线程同步-Event-lock
目录 1 线程同步 1.1 Event 1.1.1 什么是Flag? 1.1.2 Event原理 1.1.3 吃包子 1.2 Lock 1.2.1 lock方法 1.2.2 计数器 1.2.3 非阻塞 ...
- git clone的
git clone git@e.coding.net:wudi360/*******.git
- (转)Opencv卷积操作
转自:http://www.2cto.com/kf/201312/267308.html Mask Operation filter2D函数 Last Edit 2013/12/24 所谓的Mask ...