【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; ...
随机推荐
- 高效vim插件
目录[-] 高效vim插件 插件管理利器 高效插件集 NerdTree snipMate tagbar jedi-vim eclim c.vim vim-colorschemes vim配置 一个实例 ...
- NBUT 1114 Alice's Puppets(排序统计,水)
题意:给一棵人名树,按层输出,同层则按名字的字典序输出. 思路:首先对每个人名做索引,确定其在哪一层,按层装进一个set,再按层输出就自动排好序了. #include <bits/stdc++. ...
- js 分组数组
思路: 1.先将数组按照一定规则排序: 2.再拆分数组到Map中,按Key分类: 3.再从Map中遍历取出要显示的内容: sortBroadList: function (broadcastList) ...
- urllib基础-构造请求对象,设置用户代理User-Agent
有的网页具有一些反爬机制,如:需要浏览器请求头中的User-Agent.User-Agent类似浏览器的身份证. 程序中不设置User-Agent.默认是Python-urllib/3.5.这样网站就 ...
- Java MiniUi datagrid加载数据时,如果使用virtualScroll="false",数据多一点可能就会加载不出来
datagrid的值为 virtualScroll="true" 问题解决.
- 快学UiAutomator各种框架介绍
Monkey 编写语言:命令行 运行环境:使用adb连接PC运行测试对象:Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕.滑动Trackball.按键等操作来对设备上的程 ...
- CPP-基础:友元
友元可以是一个函数,该函数被称为友元函数:友元也可以是一个类,该类被称为友元类. 我们已知道类具有封装和信息隐藏的特性.只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的.非成 ...
- DP玄学优化——斜率优化
--以此博客来悼念我在\(QBXT\)懵逼的时光 \(rqy\; tql\) (日常%\(rqy\)) 概念及用途 斜率优化是\(DP\)的一种较为常用的优化(据说在高中课本里稍有提及),它可以用于优 ...
- 661. Image Smoother@python
Given a 2D integer matrix M representing the gray scale of an image, you need to design a smoother t ...
- POJ-2251-地下城
这题是一道简单的广搜题目,读入的时候,需要注意,如果是用scanf读入的话,就直接读取每行的字符串,不然的话,行尾的回车,也会被当成字符读入,这样的话,每次读取的数目就会小于我们想要的数目,因为每次把 ...