【Luogu】P1967货车运输(最大生成森林+倍增LCA)
倍增LCA是个什么蛇皮原理啊,循环完了还得再往上跳一次才能到最近公共祖先
合着我昨天WA两次就是因为这个
建最大生成森林,因为图不一定是联通的,所以不一定是一棵树。这个地方用克鲁斯卡尔就好了
然后给这个森林跑一遍DFS,顺便倍增
然后对于每个询问跑LCA,倍增的时候已经顺便求出了最小边权,所以往上跳的同时更新答案。
代码如下
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct EDGE{
int from,to,dis;
bool operator <(const EDGE &a)const{
return dis>a.dis;
}
}que[]; int father[];
struct Edge{
int next,to,dis;
}edge[];
int head[],num;
inline void add(int from,int to,int dis){
edge[++num]=(Edge){head[from],to,dis};
head[from]=num;
} int find(int x){
if(father[x]!=x) father[x]=find(father[x]);
return father[x];
} inline void unionn(int x,int y){
x=find(x);y=find(y);
father[y]=x;
} int deep[];
int d[][];
int s[][]; void dfs(int x,int fa){
deep[x]=deep[fa]+;
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==fa) continue;
d[to][]=x;
s[to][]=edge[i].dis;
dfs(to,x);
}
}
int cnt;
int main(){
int n=read(),m=read();
for(int i=;i<=m;++i){
int from=read(),to=read(),dis=read();
que[i]=(EDGE){from,to,dis};
}
std::sort(que+,que+m+);
for(int i=;i<=n;++i) father[i]=i;
for(int i=;i<=m;++i){
int from=que[i].from,to=que[i].to,dis=que[i].dis;
if(find(from)==find(to)) continue;
unionn(from,to);
add(from,to,dis);
add(to,from,dis);
if(++cnt==n-) break;
}
for(int i=;i<=n;++i)
if(!deep[i]) dfs(i,i);
for(int j=;(<<j)<=n;++j)
for(int i=;i<=n;++i){
d[i][j]=d[d[i][j-]][j-];
s[i][j]=std::min(s[d[i][j-]][j-],s[i][j-]);
}
int Q=read();
for(int i=;i<=Q;++i){
int from=read(),to=read();
if(find(from)!=find(to)){
printf("-1\n");
continue;
}
if(deep[from]<deep[to]) std::swap(from,to);
int x=deep[from]-deep[to],ans=0x7fffffff;
for(int j=;(<<j)<=x;++j)
if((<<j)&x){
ans=std::min(ans,s[from][j]);
from=d[from][j];
}
if(from==to){
printf("%d\n",ans);
continue;
}
for(int j=log2(n);j>=;--j)
if(d[from][j]!=d[to][j]){
ans=std::min(ans,std::min(s[from][j],s[to][j]));
from=d[from][j];
to=d[to][j];
}
ans=std::min(ans,std::min(s[from][],s[to][]));
printf("%d\n",ans);
}
return ;
}
完毕。
【Luogu】P1967货车运输(最大生成森林+倍增LCA)的更多相关文章
- Luogu P1967 货车运输(Kruskal重构树)
P1967 货车运输 题面 题目描述 \(A\) 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\) ,城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 \ ...
- 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA
题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ...
- 货车运输(最大生成树+倍增LCA)
看到第一篇题解的神奇码风--我决定发一篇码风正常的题解造福人类 这题的做法也非常经典,最大生成树\(+LCA\),相当于先贪心一下,在LCA的时候记录一下当前最小的边权 顺便吐槽一下最后一个测试点: ...
- 【洛谷1967】货车运输(最大生成树+倍增LCA)
点此看题面 大致题意: 有\(n\)个城市和\(m\)条道路,每条道路有一个限重.多组询问,每次询问从\(x\)到\(y\)的最大载重为多少. 一个贪心的想法 首先,让我们来贪心一波. 由于要求最大载 ...
- Luogu P1967 货车运输 倍增+最大生成树
看见某大佬在做,决定补一发题解$qwq$ 首先跑出最大生成树(注意有可能不连通),然后我们要求的就是树上两点间路径上的最小边权. 我们用倍增的思路跑出来$w[u][j]$,表示$u$与的它$2^j$的 ...
- LUOGU P1967 货车运输(最大生成树+树剖+线段树)
传送门 解题思路 货车所走的路径一定是最大生成树上的路径,所以先跑一个最大生成树,之后就是求一条路径上的最小值,用树剖+线段树,注意图可能不连通.将边权下放到点权上,但x,y路径上的lca的答案不能算 ...
- Luogu P1967 货车运输
qwq 这题是知道了正解做法才写的.. 求每两点间最小权值最大的路径,本来我以为要每个点都跑一遍dij(?),后来意识到生成树好像是用来找这个的( ´▽`) 然后我问dtxdalao对不对,他说“我记 ...
- NOIP2013D1T3货车运输(最大生成树+倍增lca)
传送门 这道题,先用kruskal求一遍图中的最大生成树. 然后,倍增求lca,求lca的同时求出边权的最小值. #include <cstring> #include <cstdi ...
- 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增
倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...
随机推荐
- NSTimer 实现时钟回调方法
在开发过程中,发现时钟调用的地方比较多.所以对时钟进行了一个简单的统一封装.具体代码如下: 1.时钟回调函数的声明: #pragma mark 时钟回调处理 //时钟回调 +(NSTimer*) ls ...
- MySQL流程控制和存储过程介绍
/*定义变量方式1:set @变量名=值;方式2:select 值 into @变量名;方式3:declare 变量名 类型(字符串类型加范围) default 值; in参数 入参的值会仅在存储过程 ...
- 快速生成导入亿级测试数据到sqlserver
如果采用insert into 循环一条一条插入速度比较慢 可以先将数据插入临时表,然后在临时表数据量到达批量插入的行数时执行例如:目标表 (col1,col2,col3) --根据目标表结构复制一个 ...
- sql视图和表的区别
整理一下视图和表的区别 区别: 1.视图是已经编译好了的sql,表不是 2.视图没有实际的物理存储记录,表有 3.视图是逻辑概念,表可以进行修改 5.表是内模式,视图是外模式 6.视图是我们查看表的方 ...
- WPF知识点全攻略04- XAML页面布局
名称 说明 Canvas 使用固定坐标绝对定位元素 StackPanel 在水平或竖直方向放置元素 DockPanel 根据外部容器边界,自动调整元素 WrapPanel 在可换行的行中放置元素 Gr ...
- mysql安装(docker)
mkdir /opt/mysql vim /opt/mysql/Dockerfile 5.7 FROM alpine FROM mysql:5.7.26 EXPOSE 3306 8.0 FROM al ...
- CPP-网络/通信:SOCKET
客户端实现代码: //引入头文件 #include <WinSock2.h> //客户端创建Socket////////////////////////////////////////// ...
- visual c++ build tools的安装与使用
https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=BuildTools&r ...
- k8s master init and add node
目录 一. add google apt-key 二. k8s master init 三. k8s node add to master cluster(use this command when ...
- quartz测试类
package demo.mytest; import java.text.ParseException; import org.quartz.CronTrigger;import org.quart ...