P1967 货车运输

题目描述

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

说明

对于 100%的数据,0 < 城市数n < 10,000,0 < 道路数m < 50,000,0 < 询问数q< 30,000,0 ≤ 限重z ≤ 100,000。


鉴于这是个稀疏图,我们用kruskal。

最小生成树有一个定理,就是边集中最大的边最小

那么我们魔改一下kruskal使它变成求最大生成树,就有最小边最大的定理。

之后就可以通过一些手段来处理造出来的生成树了

树链剖分辣么长,懒得打

所以博主这儿用的倍增

f1[i][j]表示i点往上跳2^j距离到达的点

f2[i][j]表示i点往上跳2^j距离的路径上的最小值

就可以暴力求LCA辣啊哈哈哈哈

这里推荐一个更快的大佬code-> http://www.cnblogs.com/xzz_233/p/7614189.html .

代码蒯上

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gotcha()
{
register int _a=0;bool _b=1;register char _c=getchar();
while(_c<'0' || _c>'9'){if(_c=='-')_b=0;_c=getchar();}
while(_c>='0' && _c<='9')_a=_a*10+_c-48,_c=getchar();
return _b?_a:-_a;
}
const int _ = 10002;
using namespace std;
struct edge{int to,ne,len;edge(){to=ne=len=0;}}e[10*_];
struct sav
{
int fr,to,len;sav(){fr=to=len=0;}
const bool operator < (const sav &b)const{return len>b.len;}
}tp[5*_];
int he[_],ecnt=0,dep[_],f1[_][18],f2[_][18],n,m,fa[_],gfa[_];
void add(int fr,int to,int len)
{e[++ecnt].to=to,e[ecnt].len=len,e[ecnt].ne=he[fr],he[fr]=ecnt;}
int finder(int a){return gfa[a]!=a?gfa[a]=finder(gfa[a]):a;}
void link(int a,int b){gfa[finder(b)]=finder(a);}
void plant(int a)
{
for(int i=he[a],j;i;i=e[i].ne)
{
j=e[i].to;if(j==fa[a])continue;
fa[j]=a,f1[j][0]=a,f2[j][0]=e[i].len,dep[j]=dep[a]+1,plant(j);
}
}
int driver(int st,int ta)
{
register int i,mi=2e9;
if(dep[st]>dep[ta])
for(i=16;i>=0;i--)if(f1[st][i]!=0 && dep[f1[st][i]]>=dep[ta])
mi=min(mi,f2[st][i]),st=f1[st][i];
if(dep[ta]>dep[st])
for(i=16;i>=0;i--)if(f1[ta][i]!=0 && dep[f1[ta][i]]>=dep[st])
mi=min(mi,f2[ta][i]),ta=f1[ta][i];
if(st==ta)return mi;
for(i=16;i>=0;i--)if(f1[st][i]!=f1[ta][i])
mi=min(mi,min(f2[st][i],f2[ta][i])),st=f1[st][i],ta=f1[ta][i];
return min(mi,min(f2[st][0],f2[ta][0]));
}
int main()
{
register int i,j,k;
n=gotcha(),m=gotcha();
for(i=1;i<=n;i++)gfa[i]=i;
for(i=1;i<=m;i++)tp[i].fr=gotcha(),tp[i].to=gotcha(),tp[i].len=gotcha();
sort(tp+1,tp+m+1);
for(i=1;i<=m;i++)
if(finder(tp[i].fr)!=finder(tp[i].to))
{
link(tp[i].fr,tp[i].to);
add(tp[i].fr,tp[i].to,tp[i].len),add(tp[i].to,tp[i].fr,tp[i].len);
}
for(i=1;i<=n;i++)if(i==gfa[i])fa[i]=i,dep[i]=1,plant(i);
for(i=1;i<=16;i++)
for(j=1;j<=n;j++)
{
f1[j][i]=f1[f1[j][i-1]][i-1];
f2[j][i]=min(f2[j][i-1],f2[f1[j][i-1]][i-1]);
}
i=gotcha();
while(i--)
{
j=gotcha(),k=gotcha();
printf("%d\n",(finder(j)==finder(k)?driver(j,k):-1));
}
return 0;
}

kruskal - 倍增 - 并查集 - Luogu 1967 货车运输的更多相关文章

  1. [luogu 1967]货车运输

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

  2. luogu 1967 货车运输(最大生成树+LCA)

    题意:给出一颗n个点的图,q个询问,每次询问u到v的路径中最小的边最大是多少. 图的最大生成树有一个性质,对于该图的任意两个点,在树中他们之间路径的最小边最大. 由于这个图不一定联通,于是我们对它的联 ...

  3. 洛谷P3295 萌萌哒 [SCOI2016] 倍增+并查集

    正解:倍增+并查集 解题报告: 传送门! 首先不难想到暴力?就考虑把区间相等转化成对应点对相等,然后直接对应点连边,最后求有几个连通块就好辣 然后看下复杂度,修改是O(n2)查询是O(n),就比较容易 ...

  4. 最小生成树(Minimum Spanning Tree)——Prim算法与Kruskal算法+并查集

    最小生成树——Minimum Spanning Tree,是图论中比较重要的模型,通常用于解决实际生活中的路径代价最小一类的问题.我们首先用通俗的语言解释它的定义: 对于有n个节点的有权无向连通图,寻 ...

  5. 货车运输-洛谷-1967-LCA+最大生成树(kruskal(并查集))

    传送门 一道:LCA+最大生成树 个人认为把这两个的板子写好(并熟练掌握了之后)就没什么难的 (但我还是de了好久bug)qwq 最大生成树:其实就是最小生成树的变形 我用的是kruskal (个人觉 ...

  6. Luogu P1967 货车运输(Kruskal重构树)

    P1967 货车运输 题面 题目描述 \(A\) 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\) ,城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 \ ...

  7. [SCOI2016]萌萌哒(倍增+并查集)

    一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1 ...

  8. 【BZOJ 4569】 4569: [Scoi2016]萌萌哒 (倍增+并查集)

    4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 865  Solved: 414 Description 一个长 ...

  9. 模板——最小生成树kruskal算法+并查集数据结构

    并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...

随机推荐

  1. Servlet之sendRedirect和getRequestDispatch

    Servlet的请求重定向和请求转发方法的比较分析: 1.getRequestDispatch是属于httpServletRequest对象的方法,请求转发是在同一个请求中完成的,因此整个过程只包含一 ...

  2. restframework安装及APIView分析

    一.restframework的安装 方式一:pip3 install djangorestframework 方式二:pycharm图形化界面安装 方式三:pycharm命令行下安装(装在当前工程所 ...

  3. Android的bitmap和优化

    内存管理是个永恒的话题! 内存溢出:就是分配的内存不足以放下数据项序列.如在一个域中输入的数据超过了它的要求就会引发数据溢出问题,多余的数据就可以作为指令在计算机上运行.就是你要求分配的内存超出了系统 ...

  4. azure powershell 获取可用镜像列表

    通过Azure Powershell 指定location和Pbulishername 获取所有可用镜像的 publisherName,Offer,Skus,Version,location信息列表 ...

  5. UVALive 3938 Ray, Pass me the dishes! (动态最大连续和)

    题意:求一个动态区间的最大连续和. 静态版本的O(n)算法显示不适用了,但是可以用线段树分治,因为一个连续和要在两边的区间,要么跨越两边,对于一个结点维护最大前缀和,后缀和,子区间连续和. 题目要求输 ...

  6. codeforce Gym 100500H ICPC Quest (简单dp)

    题意:给一个nXm的矩阵,上面有一些数字,从左上角出发,每次只能往右或者往下,把沿途的数字加起来,求到达右下角的最大值是多少. 题解:简单的一个dp,设f[i][j]为到达i行j列的最大值,f[i][ ...

  7. mysql命令行导出导入,附加数据库

    MySQL命令行导出数据库:1,进入MySQL目录下的bin文件夹:cd MySQL中到bin文件夹的目录如我输入的命令行:cd C:\Program Files\MySQL\MySQL Server ...

  8. mongodb 导入导出

    F:\Mongodb\bin>mongoexport.exe -h localhost:27017 -d proxy_db -c proxy_tb -o f:/p1.json 导出 -h 服务器 ...

  9. Python——函数基础

    函数是什么 它相当于一个独立的代码块,可以被重复使用,如果需要增加一个功能或者修改一个功能,只需要,增加或者修改函数即可. 函数分类 内置函数 python解释器已经为我们定义好的参数,比如:len( ...

  10. oracle中print_table存储过程实例介绍

    oracle中pro_print_table存储过程实例介绍 存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过编译后存储在数据库系统中.这 ...