【洛谷1967】货车运输(最大生成树+倍增LCA)
大致题意: 有\(n\)个城市和\(m\)条道路,每条道路有一个限重。多组询问,每次询问从\(x\)到\(y\)的最大载重为多少。
一个贪心的想法
首先,让我们来贪心一波。
由于要求最大载重,显然要让最小限重尽量大。
不难发现,想要让最小限重尽量大,所经过的路径一定都在原图的最大生成树上。
于是,我们就可以用求最大生成树的方法来将原图转化为一棵树。
这样一来,原题就转化成了求树上两点之间的最小边权值。
这应该是可以直接用倍增\(LCA\) 来搞的吧。
如何用倍增\(LCA\)求树上两点之间的最小边权值
不难想到,我们可以用\(Min_{i,j}\)来表示从\(i\)到\(fa_{i,j}\) 所经过的路径上的最小边权值。
因此,我们只需在\(LCA\)的过程中每一次更新节点为当前节点祖先时,加上更新最小值的步骤即可,代码还是很简洁的。
代码
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
#define N 10000
#define M 50000
#define add(x,y,z) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=z)
int FoutSize=0,OutputTop=0;char Fin[Fsize],*FinNow=Fin,*FinEnd=Fin,Fout[Fsize],OutputStack[Fsize];
using namespace std;
int n,m,ee=0,fa[N+5],lnk[N+5]={0},Depth[N+5],vis[N+5]={0},f[N+5][20],Min[N+5][20];
struct line//题目中给定图的边
{
int x,y,v;
}w[M+5];
struct edge//原图最大生成树的边
{
int to,nxt,val;
}e[2*N+5];
inline void read(int &x)
{
x=0;static char ch;
while(!isdigit(ch=tc()));
while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
}
inline void write(int x)
{
if(!x) return (void)pc('0');
while(x) OutputStack[++OutputTop]=x%10+48,x/=10;
while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;
}
inline bool cmp(line x,line y)//将原图给定的边排序
{
return x.v>y.v;
}
inline int getfa(int x)//并查集函数
{
return fa[x]^x?fa[x]=getfa(fa[x]):x;
}
inline void dfs(int x)//dfs初始化
{
register int i;
for(i=1;i<20;++i) f[x][i]=f[f[x][i-1]][i-1],Min[x][i]=min(Min[x][i-1],Min[f[x][i-1]][i-1]);//计算出f数组和Min数组
for(vis[x]=1,i=lnk[x];i;i=e[i].nxt)//枚举当前节点的相邻节点
{
if(!(e[i].to^f[x][0])) continue;//如果枚举到的节点是当前节点的父亲节点,就跳过
Depth[e[i].to]=Depth[f[e[i].to][0]=x]+1,Min[e[i].to][0]=e[i].val,dfs(e[i].to);//初始化子节点信息,并dfs该子节点
}
}
inline int Query(int x,int y)//询问操作,类似于求LCA的过程
{
register int i,res=1e9;//res记录答案
if(Depth[x]<Depth[y]) swap(x,y);
for(i=0;Depth[x]^Depth[y];++i) if((Depth[x]-Depth[y])&(1<<i)) res=min(res,Min[x][i]),x=f[x][i];//在更新当前节点为当前节点祖先的同时,也要更新最小值
if(!(x^y)) return res;//如果x与y已经相等,就返回res
for(i=0;f[x][i]^f[y][i];++i);
for(--i;i>=0;--i) if(f[x][i]^f[y][i]) res=min(res,min(Min[x][i],Min[y][i])),x=f[x][i],y=f[y][i];//在更新当前节点为当前节点祖先的同时,也要更新最小值
return min(res,min(Min[x][0],Min[y][0]));//返回x,y到父亲的边权与res中的较小值
}
int main()
{
register int i,Q,x,y,fx,fy;
for(read(n),read(m),i=1;i<=m;++i) read(w[i].x),read(w[i].y),read(w[i].v);//读入原图
for(sort(w+1,w+m+1,cmp),i=1;i<=n;++i) fa[i]=i;//初始化并查集
for(i=1;i<=m;++i) if((fx=getfa(w[i].x))^(fy=getfa(w[i].y))) fa[fx]=fy,add(w[i].x,w[i].y,w[i].v),add(w[i].y,w[i].x,w[i].v);//Kruskal最大生成树
for(read(Q);Q;--Q)//对于每个询问进行操作
{
read(x),read(y);
if(getfa(x)^getfa(y)) {pc('-'),pc('1'),pc('\n');continue;}//如果不在同一个联通块内,直接输出-1
if(!vis[x]||!vis[y]) dfs(x);//如果这个联通块未访问过,就dfs遍历一遍初始化
write(Query(x,y)),pc('\n');//输出两点之间的最小边权
}
return fwrite(Fout,1,FoutSize,stdout),0;
}
【洛谷1967】货车运输(最大生成树+倍增LCA)的更多相关文章
- TZOJ 4848 货车运输(最大生成树+倍增lca)
描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多 ...
- 洛谷1967货车运输 即 NOIP2013 DAY1 T3
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- $Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$
$Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的 ...
- 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增
倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...
- 洛谷 P1967 货车运输
洛谷 P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在 ...
- [洛谷 P1967] 货车运输 (最大生成树 lca)
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- 洛谷P1967货车运输——倍增LCA
题目:https://www.luogu.org/problemnew/show/P1967 就是倍增LCA的裸题,注意一些细节即可. 代码如下: #include<iostream> # ...
- 【杂题总汇】NOIP2013(洛谷P1967) 货车运输
[洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...
- 洛谷 P1967 货车运输 Label: 倍增LCA && 最小瓶颈路
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- 洛谷—— P1967 货车运输 || COGS——C 1439. [NOIP2013]货车运输
https://www.luogu.org/problem/show?pid=1967#sub || http://www.cogs.pro/cogs/problem/problem.php?pi ...
随机推荐
- ARC085E(最小割规划【最大流】,Dinic当前弧优化)
#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll inf=0x3f3f3f3f;int cn ...
- Spark Checkpoint 概述
有时候,Transformation 的 RDD 非常多或者具体 Transformation 产生的 RDD 本身计算特别复杂和耗时,此时我们必须考虑对计算结果数据进行持久化.与 persist 不 ...
- hdu2874(lca / tarjan离线 + RMQ在线)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意: 给出 n 个顶点 m 条边的一个森林, 有 k 个形如 x y 的询问, 输出 x, ...
- [转][iOS Crash文件分析]-如何使用symbolicatecrash工具
上传一软件,被拒了,自己测试了n遍都未出现这个情况,今天用symbolicatecrash工具分析了一下苹果提供的Crash文件,最终查到是 - (void)mapView:(MKMapView *) ...
- Java 引用类型
若内存中一个对象没有任何引用的话,则可以认为该对象已经不再使用了,可以成为GC的候选.不过由于垃圾回收器的运行时间不确定,可被垃圾回收的对象的实际被回收时间是不确定的.对于一个对象来说,只要有引用的存 ...
- [USACO08JAN]跑步Running dp
题目描述 The cows are trying to become better athletes, so Bessie is running on a track for exactly N (1 ...
- POJ1010 Stamps
题目来源:http://poj.org/problem?id=1010 题目大意: 某邮局要设计新的邮资管理软件,依据顾客的需要和现有的面值给顾客分派邮票. 该邮局有很多顾客是集邮爱好者.这些人希望得 ...
- sourcetree基本使用
非常有用的使用sourcetree开发的步骤文档 https://www.cnblogs.com/fps2tao/p/7825742.html 1) master,最终发布版本,整个项目中有且只有一个 ...
- 原生DOM操作方法小结
1.0 DOM结构 父节点 兄弟节点 当前节点 属性节点 子节点 兄弟节点 一般任意一个节点我们都会从父节点,子节点,以及兄弟节点的角度去考察.节点一般我们只需关注元素节点,属性节点及文本节点即可 ...
- P2062 分队问题(贪心orDP)
题目描述 给定n个选手,将他们分成若干只队伍.其中第i个选手要求自己所属的队伍的人数大等于a[i]人. 在满足所有选手的要求的前提下,最大化队伍的总数. 注:每个选手属于且仅属于一支队伍. 输入输出格 ...