描述

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入

第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。

接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

输出

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

样例输入

4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3

样例输出

3
-1
3

提示

对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000;

对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000;

对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。

题意

如上

题解

要使路径上的最小值尽可能大,跑一个最大生成树

然后在查询树上路径最小值的时候,可以跑一个倍增lca

查询u,v的最小值的时候,先找到u,v的公共祖先p,再求min(up的最小值,vp的最小值)

代码

 #include<bits/stdc++.h>
using namespace std; const int maxn=;
const int maxm=;
int deep[maxn],fa[maxn][],dis[maxn][],lg[maxn],vis[maxn],f[maxn],n,m;
vector< pair<int,int> >G[maxn];
struct edge
{
int u,v,w;
bool operator<(const edge &D)const{
return w>D.w;
}
}edges[maxm];
void dfs(int u)
{
vis[u]=;
for(auto X:G[u])
{
int v=X.first;
int w=X.second;
if(vis[v])continue;
fa[v][]=u;
dis[v][]=w;
deep[v]=deep[u]+;
dfs(v);
}
}
void RNQ()
{
for(int j=;(<<j)<=n;j++)
for(int i=;i<=n;i++)
fa[i][j]=fa[fa[i][j-]][j-],
dis[i][j]=min(dis[i][j-],dis[fa[i][j-]][j-]);
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
while(deep[x]>deep[y])x=fa[x][lg[deep[x]-deep[y]]-];
if(x==y)return x;
for(int k=lg[deep[x]];k>=;k--)
if(fa[x][k]!=fa[y][k])
x=fa[x][k],y=fa[y][k];
return fa[x][];
}
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int query(int x,int y)
{
int ans=0x3f3f3f3f,t=deep[x]-deep[y];
for(int i=;i<=;i++)
if(t&(<<i))
ans=min(ans,dis[x][i]),
x=fa[x][i];
return ans;
}
void max_kruskal()
{
int cnt=;
sort(edges,edges+m);
for(int i=;i<m;i++)
{
int u=edges[i].u;
int v=edges[i].v;
int w=edges[i].w;
int fu=find(u);
int fv=find(v);
if(fu!=fv)
{
G[u].push_back({v,w});
G[v].push_back({u,w});
f[fu]=fv;
if(++cnt==n-)break;
}
}
}
int main()
{
memset(dis,0x3f3f3f3f,sizeof dis);
memset(vis,false,sizeof vis);
int u,v,w,q;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)lg[i]=lg[i-]+(<<lg[i-]==i),f[i]=i;
for(int i=;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
edges[i]={u,v,w};
}
max_kruskal();
for(int i=;i<=n;i++)if(!vis[i])dfs(i);
RNQ();
scanf("%d",&q);
for(int i=;i<q;i++)
{
scanf("%d%d",&u,&v);
if(find(u)!=find(v))printf("-1\n");
else
{
int father=lca(u,v);
printf("%d\n",min(query(u,father),query(v,father)));
}
}
return ;
}

TZOJ 4848 货车运输(最大生成树+倍增lca)的更多相关文章

  1. $Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$

    $Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的 ...

  2. 【NOIP2013】货车运输 最大生成树+倍增

    题目大意:给你一张n个点m条边的图,有q次询问,每次让你找出一条从x至y的路径,使得路径上经过的边的最小值最大,输出这个最大的最小值. 显然,经过的路径必然在这张图的最大生成树上. 我们求出这个图的最 ...

  3. 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA

    题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ...

  4. 货车运输(最大生成树+倍增LCA)

    看到第一篇题解的神奇码风--我决定发一篇码风正常的题解造福人类 这题的做法也非常经典,最大生成树\(+LCA\),相当于先贪心一下,在LCA的时候记录一下当前最小的边权 顺便吐槽一下最后一个测试点: ...

  5. 【洛谷1967】货车运输(最大生成树+倍增LCA)

    点此看题面 大致题意: 有\(n\)个城市和\(m\)条道路,每条道路有一个限重.多组询问,每次询问从\(x\)到\(y\)的最大载重为多少. 一个贪心的想法 首先,让我们来贪心一波. 由于要求最大载 ...

  6. 货车运输 noip2013 luogu P1967 (最大生成树+倍增LCA)

    luogu题目传送门! 首先,题目让我们求每个货车的最大运输量,翻译一下就是求路径上边权最小的边. 利用一下贪心思想可知,所有货车肯定都会尽量往大的边走. 进一步翻译,即为有一些小边货车根本不会走,或 ...

  7. NOIP2013D1T3货车运输(最大生成树+倍增lca)

    传送门 这道题,先用kruskal求一遍图中的最大生成树. 然后,倍增求lca,求lca的同时求出边权的最小值. #include <cstring> #include <cstdi ...

  8. 【NOIP2013】货车运输 最大生成树+LCA

    题目描述 AA国有nn座城市,编号从 1到n,城市之间有m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重 ...

  9. Luogu1967 NOIP2013 货车运输 最大生成树、倍增

    传送门 题意:给出一个$N$个节点.$M$条边的图,$Q$次询问,每一次询问两个点之间的所有可行路径中经过的边的边权的最小值中的最大值.$N \leq 10000 , M \leq 50000 , Q ...

随机推荐

  1. 学习opengl第一步

    有两个地址一个是学习opengl基础知识的网站, 一个是博客园大牛分享的特别好的文章. 记录一下希望向坚持做俯卧撑一样坚持下去. 学习网站:http://learnopengl-cn.readthed ...

  2. 【374】Adobe Acrobat 操作技巧

    1. 文件内容增减 参考:如何在PDF文件中删除页面 参考:如何旋转.移动.删除和重新编号 PDF 页面 双击PDF文档,并在预览程序中打开它. 如果在其他程序(如Adobe Reader)中打开文档 ...

  3. python常用字符串处理(转)

    转自https://www.cnblogs.com/houht/p/3308634.html 判断字符串str是否为空 Approach 1:如果字符串长度为0,说明字符串为空,code如下: isN ...

  4. mysql 5.7.3.0-m13安装教程

    安装mysql百度经验地址:(默认安装,除了选择不更新和选择保存路径,其它基本是下一步下一步) http://jingyan.baidu.com/article/7e440953d6f0702fc1e ...

  5. C#图像处理:截图程序(包含鼠标)

    截图后在picbox中显示,用定时器定时每毫秒截图一次,在picbox上显示就有动画效果.代码: [DllImport("user32.dll")] static extern b ...

  6. QuickSand图片点击后分裂成几份消失效果《IT蓝豹》

    QuickSand图片点击后分裂成几份消失效果 QuickSand图片点击后分裂成几份消失效果,适合做图片退出和剪切效果.同时也可以学习android动画. demo中都封装好几个功能类,主要动画实现 ...

  7. Android-Anim-Playground

    Android-Anim-Playground Latest animation ideas I developed to make apps more attractive. Why having ...

  8. export default 与 export

    export default 只能导出一个 可以用任意的变量来接收 export 可以暴露多个成员,需要用 import {} 接受成员 需要用名字接受 名字必须跟导出名字一致  //或者as作为别名 ...

  9. video 播放本地视屏

    var file = document.getElementById('file_video').files[0]; var url = URL.createObjectURL(file); docu ...

  10. android Zxing 扫描区域的大小设置和自定义扫描view

    自己的项目中,只需要修改: CameraManager 里面的 MAX_FRAME_WIDTH .MAX_FRAME_HEIGHT 的值 private static final int MIN_FR ...