https://www.luogu.org/problemnew/show/P1967

由题可知,我们走的路的边应尽可能大,所以通过$kruscal$建最大生成树的图,再树上倍增,注意可能有多棵树;

#include <bits/stdc++.h>
#define read read()
#define up(i,l,r) for(register int i = (l);i <= (r);i++)
#define down(i,l,r) for(register int i = (l);i >= (r);i--)
#define traversal_vedge(i) for(register int i = head[u]; i ;i = e[i].nxt)
#define ll long long
using namespace std;
int read
{
int x = , f = ; char ch = getchar();
while(ch < || ch > ) {if(ch == '-')f = -; ch = getchar();}
while(ch >= && ch <=) {x = * x + ch - ;ch = getchar();}
return x * f;
}
const int N = 1e4+,M = 5e5+,inf = 0x3f3f3f3f;
int n,m,q,f[N];
struct kedge{
int u,v,limit;
bool operator < (const kedge &x) const{
return limit > x.limit;
}
}ke[M<<]; struct edge{
int v,limit,nxt;
}e[M<<];int tot,head[N]; void build_tree(int u,int v,int w) {e[++tot] = (edge){v,w,head[u]}; head[u] = tot;} //-----------------------------------------------------------------
int find(int i) {if(f[i] == i) return i;f[i] = find(f[i]);return f[i]; }
void kruscal(){
sort(ke+,ke+m+);
up(i,,n) f[i] = i;
int cnt = ;
up(i,,m)
{
if(cnt == n-) break;
if(find(ke[i].u) != find(ke[i].v))
{
f[f[ke[i].u]] = f[ke[i].v];
cnt++;
build_tree(ke[i].u,ke[i].v,ke[i].limit);
build_tree(ke[i].v,ke[i].u,ke[i].limit);//debug ke[i].u -> ke[i].v;
}
else continue;
}
}
//----------------------------------------------------------------------- int fa[N][],mine[N][],dep[N],vis[N];//debug 15 ->14 void dfs(int u,int f,int w){
vis[u] = ;
dep[u] = dep[f] + ;
fa[u][] = f;
mine[u][] = w;
for(int i = ; (<<i) <= dep[u]; i++)
{
fa[u][i] = fa[fa[u][i-]][i-];
mine[u][i] = min(mine[u][i-],mine[fa[u][i-]][i-]);
}
traversal_vedge(i)
{
int v = e[i].v;
if(v == f) continue;
dfs(v,u,e[i].limit);
}
} /*int LCA(int x,int y){
if(dep[x] < dep[y]) swap(x,y);
down(i,14,0)
{
if(dep[fa[x][i]] >= dep[y])
x = fa[x][i];
}
if(x == y) return x;
down(i,14,0)
{
if(fa[x][i] != fa[y][i])
{
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}*/
//----------------------------------------------------------------- int query(int x,int y)
{
int ans = inf;
if(dep[x] < dep[y]) swap(x,y);
down(i,,)
{
if(dep[fa[x][i]] >= dep[y])
{
ans = min(ans,mine[x][i]);
x = fa[x][i];
}
}
if(x == y) return ans;
down(i,,)
{
if(fa[x][i] != fa[y][i])
{
ans = min(ans,min(mine[x][i],mine[y][i]));
x = fa[x][i];
y = fa[y][i];
}
}
ans = min(ans,min(mine[x][],mine[y][]));
return ans;
} /*int query(int x,int lca){
//if(x == lca) return 0x3f3f3f3f;
int i = 0;
while(dep[fa[x][i]] > dep[lca] ) i++;
return mine[x][i];
}*/ void work(){
kruscal();
memset(mine,0x3f,sizeof(mine));
//debug 未考虑多棵树
up(i,,n)
{
if(!vis[i])
dfs(i,,inf);
}
q = read;
while(q--)
{
int x = read, y = read;
if(find(x) != find(y))
{
printf("-1\n");
continue;
}
//int lca = LCA(x,y);
//ans = min(query(x,lca),query(y,lca));
printf("%d\n",query(x,y));
}
} void readdata()
{
n = read; m = read;
up(i,,m)
{
ke[i].u = read; ke[i].v = read; ke[i].limit = read;
}
} int main()
{
freopen("input21.txt","r",stdin);
//freopen("output21.out","w",stdout);
readdata();
work();
return ;
}

最开始的写法之所以是错误的,是因为会多求一段,而我们只需要求到LCA就行;

【NOIP2013/Codevs3287】货车运输-最小生成树(大)-树上倍增的更多相关文章

  1. [NOIP2013/Codevs3287]货车运输-最小[大]生成树-树上倍增

    Problem 树上倍增 题目大意 给出一个图,给出若干个点对u,v,求u,v的一条路径,该路径上最小的边权值最大. Solution 看到这个题第一反应是图论.. 然而,任意路径最小的边权值最大,如 ...

  2. xsy 2018 【NOIP2013】货车运输

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

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

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

  4. codevs3287货车运输(最小生成树+LCA)

    3287 货车运输 2013年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description A 国有 ...

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

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

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

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

  7. C++之路进阶——codevs3287(货车运输)

    3287 货车运输 2013年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description A 国有 n ...

  8. NOIP2013 D1T3 货车运输 zz耻辱记

    目录 先来证明下lemma: 图上2点间最小边权最大的路径一定在MST上 感性理解下: 每次kruskal algo都连接最大的不成环边 此时有2个未联通的联通块被连起来. 那么考虑u, v两点的联通 ...

  9. NOIP2013 D1T3 货车运输

    [NOIP2013T3]货车运输 背景 noip2013day1 描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重 量限制,简称限重.现在有 q 辆货 ...

随机推荐

  1. Python 面向对象(三)

    继承的实现原理 Python支持多继承 多继承的时候  属性查找的顺序 研究经典类和新式类在属性查找的不同 主要是形成菱形关系才有深度跟广度 广度优先 Python的继承原理  Python3的内置方 ...

  2. eclipse常用快捷键整理

    Ctrl + F11 按上次方式执行 Ctrl + Shift + / 加上注释/**/ Ctrl + Shift + \ 取消注释/**/ Ctrl + / 加上或消除行注释 Ctrl + D 删除 ...

  3. Github 大牛封装 Python 代码,实现自动发送邮件只需三行代码

    *注意:全文代码可左右滑动观看 在运维开发中,使用 Python 发送邮件是一个非常常见的应用场景.今天一起来探讨一下,GitHub 的大牛门是如何使用 Python 封装发送邮件代码的. 一般发邮件 ...

  4. 如何在ORACLE中查询某一用户下所有的空表

    先分析表 select 'analyze table '||table_name||' compute statistics;' from user_tables; 把查询结果依次执行 把所有表分析一 ...

  5. windows清空电脑的DNS缓存

    清空电脑的DNS缓存 按"Win+R"系统热键打开"运行"窗口,进入terminal终端 输入"ipconfig /flushdns"命令后 ...

  6. uva-10602-贪心

    题意:有个编辑器,支持三种操作,摁下一个键盘上的字符,重复最后一个单词,删除最后一个字符.给N个字符串,必须先在编辑器内输入第一个字符, 问,输入完所有字符串最少需要摁下多少次键盘. 最多100个字符 ...

  7. Dubbo注册Zookepper服务的虚拟IP

    使用dubbo在zookepper上注册服务,使用dubbo的服务器IP为192.168.70.105 而在zookepper上显示服务提供者为 dubbo://202.102.110.203:808 ...

  8. laravel表单操作

    $request->all()//获取所有参数if($request->isMethod('GET')){判断是否是GET请求}$res = $request->is('studen ...

  9. Mac 笔记本 开发日记

    1.录屏,截图 Mac 自带录屏功能 command +control +o 2.复制当前应用,在启一个当前app窗口 command+n 3.快速回到桌面 command +f3 4.选中文件,复制 ...

  10. ReactiveX 学习笔记(23)RxCpp

    RxCpp RxCpp 是 ReactiveX 的 C++ 语言实现. 下载 RxCpp $ git clone --recursive https://github.com/ReactiveX/Rx ...