P1967 货车运输
传送门
算法:最大生成树 & LCA
题目要求两点之间最小边权 的最大值..
就是两点之间有多条路径,每条路径有一个 最小边权
要找到最大的 最小边权
考虑kruskal算法的过程
如果我们每次把能使图两个块联通的最大的边加入图中
那么最终出来的图就称为最大生成树
显然 在最大生成树中,两点之间的路径一定是题目要求的最小边权最大的路径
因为如果有更优的一条路可以替代原本的路,那么在之前求最大生成树的过程中就会被选择
好吧可能不太清楚,换个说法:
在kruskal过程时
假设已经选了几条边
现在我们要找一条边能使其中两个块联通
联通完后车就可以从一个块走到另一个块
那么我们要找哪条边呢
显然是最大的边
如果选比较小的边
那还不如选更大的边,还可以尽量增加车的最大载重
对于任意的块都显然成立
所以要建最大生成树
建完了然后就是处理询问
不能直接暴力,询问太多
想想要怎么快速处理出树上两点间的询问呢
我会树链剖分!
为什么要这么麻烦
考虑LCA的思想..
就这样搞:
设mi[ i ][ j ] 为从节点 i 往上2^j 段路径的最小值
然后LCA怎么搞就怎么搞了
顺便注意一下可能图不联通...
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<vector> using namespace std; struct edge {int a,b,v; }e[50005];//原来的边 int n,m,q,fa[10005],f[10005][21],dep[10005],mi[10005][21]; struct Edge {vector <int> v,dis;//vector用起来多方便啊 }ev[10001];//最大生成树的边 bool p[10005]; bool cmp(const edge a,const edge b){return a.v>b.v; } int find(int x) {if(x!=fa[x]) fa[x]=find(fa[x]);return fa[x]; }//搞kruskal当然要并查集,而且顺便可以判断两点是否联通(原图可能不联通) void dfs(int x,int father)//预处理mi {dep[x]=dep[father]+1;f[x][0]=father;for(int i=1;i<=20;i++){f[x][i]=f[f[x][i-1]][i-1];mi[x][i]=min(mi[f[x][i-1]][i-1],mi[x][i-1]);}int len=ev[x].v.size();for(int i=0;i<len;i++){int u=ev[x].v[i];if(u==father) continue;mi[u][0]=ev[x].dis[i];dfs(u,x);} } int lca(int x,int y)//求两点间路径上最短的边 {int res=99999999;if(dep[x]<dep[y]) swap(x,y);for(int i=20;i>=0;i--)if(dep[f[x][i]]>=dep[y]){ res=min(res,mi[x][i]);x=f[x][i];}if(x==y) return res;for(int i=20;i>=0;i--)if(f[x][i]!=f[y][i]){res=min(res,min(mi[x][i],mi[y][i]));x=f[x][i];y=f[y][i];}return min(res,min(mi[x][0],mi[y][0])); } int main() {memset(mi,0x7f,sizeof(mi));cin>>n>>m;for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].v);sort(e+1,e+m+1,cmp);for(int i=1;i<=m;i++){int xa=find(e[i].a),xb=find(e[i].b);if(xa==xb) continue;fa[xa]=xb;ev[e[i].a].v.push_back(e[i].b);ev[e[i].b].v.push_back(e[i].a);ev[e[i].a].dis.push_back(e[i].v);ev[e[i].b].dis.push_back(e[i].v);}//kruskal算法for(int i=1;i<=n;i++)//原图可能不联通,要把每个点找一遍 {int xa=find(i);if(p[xa]) continue;p[xa]=1;dfs(xa,xa);}cin>>q;int a,b;for(int i=1;i<=q;i++){scanf("%d%d",&a,&b);int xa=find(a),xb=find(b);if(xa!=xb){cout<<"-1"<<endl;continue;}cout<<lca(a,b)<<endl;}//处理询问return 0; }
转载于:https://www.cnblogs.com/LLTYYC/p/9534342.html
P1967 货车运输相关推荐
- 【杂题总汇】NOIP2013(洛谷P1967) 货车运输
[洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...
- noip 2013 洛谷 P1967 货车运输
题目:货车运输 大致题意: 给出一张无向带权图,对于m个询问(X,Y),要求找出X到Y的一条路径使得路径上的最小边权最大,并输出这个最小边权. 思路: 可以看出,X到Y的满足条件的路径一定在原图的最大 ...
- luogu p1967 货车运输
题意:有n座城市,其间有m条道路相连,构成无向图,图中可能存在孤点.每条道路有一个限重值,货车走这条道路时所载货物的重量不应超过限重值.有q次询问,每次询问给出两个城市,问从城市1到城市2之间货车的最 ...
- 洛谷 P1967货车运输 并查集+贪心 不需要用LCA!
题目链接 题目链接 题解 要求所有的路径中最小边长的最大值! 我们贪心的加边,依照边从大往小的方式往里添加,然后合并并查集. 每次当查询分布在两个待合并的并查集的时候,当前的边长就是这次查询的答案. ...
- P1967 货车运输( 最大生成树+LCA or Kruskal重构树)
至于为什么要用最大生成树!? 理由:因为问最大载重,如果要加大载重的话,对于选择的路肯定权重越大越好,所以贪心地想,得用到最大生成树.然后两点之间的最大载重用LCA去寻找就可以了. 最大生成树+LCA ...
- P1967 货车运输 题解
博客园同步 原题链接 简要题意: 给定一个无向图,若干组询问问 x → y x \rightarrow y x→y 所有路径上最小权值的最大值. 算法一 对于 60 % 60\% 60% 的数据, 1 ...
- 【题解】【洛谷 P1967】 货车运输
目录 洛谷 P1967 货车运输 原题 题解 思路 代码 洛谷 P1967 货车运输 原题 题面请查看洛谷 P1967 货车运输. 题解 思路 根据题面,假设我们有一个普通的图: 作图工具:Graph ...
- 【洛谷P1967】[NOIP2013]货车运输
货车运输 题目链接 显然,从一点走到另一点的路径中,最小值最大的路径一定在它的最大生成树上 所以要先求出最大生成树,再在生成树上找最近公共祖先,同时求出最小值. 1 #include<iostr ...
- 倍增LCA NOIP2013 货车运输
货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情 ...
最新文章
- 如何写好一份工程师简历
- idea 的lombok安装完不生效的办法
- java 实现中文排序,Java自定义比较器实现中文排序
- 【转】类与类之间的常见关系,uml图表示
- LeetCode--64. 最小路径和(动态规划)
- c语言迷宫算法入门,基于C语言实现的迷宫算法示例
- MATLAB频谱图绘制
- 前端和后端哪个工资更高呢?
- 【1401】机器翻译
- 苹果亮度自动调节怎么关闭_Redmi K30 Pro自动亮度调节和iPhone基本一致,安卓手机的大进步...
- 获取Orcal编码格式为US7ASCII中文数据乱码问题;
- 2022Java学习笔记八十八(网络编程:UDP通信,一发一收,多发多收消息接收实现)
- 数据分析案例—天猫品牌店铺运营报告
- 用python函数画德国国旗代码_每日一程-11.利用Python turtle库绘制国旗
- 超级计算机大赛要学什么,超级计算机竞赛“七步成诗”仅三队完赛
- Linux的Matlab使用
- 财务平台打印不完整处理及横向纵向问题
- NTC转RS-485,热敏电阻温度Modbus数据采集模块 WJ126
- iOS14桌面伪透明
- idea配置logback彩色日志