题目描述

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

解析

看我蒻到把双向边连成单向边debug了一上午。

很显然,如果只有一个询问,我们贪心地连边直到起点和终点连通即可。如果有这么多个询问,我们仍然可以像最小生成树那样如法炮制,贪心地搞一个“最大生成树”出来(我也不知道有没有),然后你甚至可以树剖。然后我们就在树上乱搞,随便用一种算法求出树上任意两点之间路径的最小权值就行了。

这里我用到了树上倍增求LCA,分别统计两个点到它们LCA的最小权值,对这两个值再取min就是最终答案。

参考代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define N 500010
#define INF 0x7fffffff
#define IN freopen("data.in","r",stdin);
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct node{
int from,to,edge;
}a[N];
struct rec{
int next,ver,edge;
}g[N];
int head[N],tot;
int fa[N],f[30][N],w[30][N],d[N],n,m;//f[i][x]表示x节点的2^i辈父亲,w[i][x]表示x节点到其2^i辈父亲的最小权值,d[x]表示节点x的深度
queue<int> q;
inline void add(int x,int y,int val)
{
g[++tot].ver=y,g[tot].edge=val;
g[tot].next=head[x],head[x]=tot;
}
inline int get(int x)
{
return fa[x]==x?x:fa[x]=get(fa[x]);
}
inline void merge(int x,int y)
{
x=get(x),y=get(y);
if(x!=y) fa[x]=y;
}
inline void init(int x)//BFS预处理f[][],w[][]
{
q.push(x);d[x]=1;
while(q.size()){
int index=q.front();q.pop();
for(int i=head[index];i;i=g[i].next){
int y=g[i].ver,z=g[i].edge;
if(d[y]) continue;
f[0][y]=index;w[0][y]=z;
d[y]=d[index]+1;
for(int j=1;j<25;++j){
f[j][y]=f[j-1][f[j-1][y]];
w[j][y]=min(w[j-1][y],w[j-1][f[j-1][y]]);//仿照ST表求法预处理w数组
}
q.push(y);
}
}
}
inline int calc(int x,int y)//倍增求LCA
{
int ans=INF;
if(d[x]>d[y]) swap(x,y);
for(int i=24;i>=0;--i)
if(d[f[i][y]]>=d[x]) ans=min(ans,w[i][y]),y=f[i][y];
if(x==y) return ans;
for(int i=24;i>=0;--i){
if(f[i][y]==f[i][x]) continue;
ans=min(ans,min(w[i][y],w[i][x])),x=f[i][x],y=f[i][y];
}
if(x==y) return ans;
ans=min(ans,min(w[0][x],w[0][y]));
return ans;
}
bool cmp(node a,node b){return a.edge>b.edge;}
int main()
{
//IN
int q;
n=read(),m=read();
for(int i=1;i<=m;++i)
a[i].from=read(),a[i].to=read(),a[i].edge=read();
sort(a+1,a+m+1,cmp);//最大生成树,并查集实现
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=1;i<=m;++i){
int x=get(a[i].from),y=get(a[i].to);
if(x==y) continue;
merge(x,y),add(a[i].from,a[i].to,a[i].edge),add(a[i].to,a[i].from,a[i].edge);
}
memset(w,0x3f,sizeof(w));
for(int i=1;i<=n;++i)
if(!d[i]) init(i);//可能出现森林
q=read();
for(int i=1;i<=q;++i){
int u,v;
u=read(),v=read();
int x=get(u),y=get(v);
if(x!=y){
printf("-1\n");continue;//如果两个点不在一棵树上,无解
}
printf("%d\n",calc(u,v));
}
return 0;
}

P1967 货车运输[生成树+LCA]的更多相关文章

  1. 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增

    倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...

  2. P1967 货车运输【LCA】【生成树】

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

  3. 洛谷P1967货车运输——倍增LCA

    题目:https://www.luogu.org/problemnew/show/P1967 就是倍增LCA的裸题,注意一些细节即可. 代码如下: #include<iostream> # ...

  4. 洛谷 P1967 货车运输

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

  5. P1967 货车运输

    P1967 货车运输最大生成树+lca+并查集 #include<iostream> #include<cstdio> #include<queue> #inclu ...

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

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

  7. 【杂题总汇】NOIP2013(洛谷P1967) 货车运输

    [洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...

  8. 洛谷P1967 货车运输

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

  9. 洛谷—— P1967 货车运输 || COGS——C 1439. [NOIP2013]货车运输

    https://www.luogu.org/problem/show?pid=1967#sub  ||  http://www.cogs.pro/cogs/problem/problem.php?pi ...

随机推荐

  1. skynet sproto 问题

    刚碰到一个小细节,纠结了半个小时 sproto的协议,request 和{ 必须有空格

  2. Python35之包的创建

    包(package) 一.创建一个文件夹,用于存放相关的模块,文件夹的名字即包的名字 二.在文件夹中创建一个__init__.py的模块文件,内容可以为空 三将相关的模块放入文件夹中 这样就相当于创建 ...

  3. 别再裸奔了,你的项目代码安全吗,再不加密就out了

    在工作中,有时候我们需要部署自己的Python代码 或进行私有化部署时,尤其现在都是通过docker镜像部署,我们并不希望别人能够看到自己的Python源程序. 加密Python源代码的方式,是将.p ...

  4. PyCharm:设置py文件头部信息

    P PyCharm:设置py文件头部信息file->setting->appearance & behavior->editor->file and code temp ...

  5. Python random模块(以后用到一个再更新一个)

    random模块是产生随机数的模块 1.random.random() 这是产生0~1之间一个随机浮点数,但是不会包括1 import random num = 0 while num < 10 ...

  6. PAT(B) 1052 卖个萌(Java:0分 待解决,C:20分)

    题目链接:1052 卖个萌 (20 point(s)) 题目描述 萌萌哒表情符号通常由"手"."眼"."口"三个主要部分组成.简单起见,我们 ...

  7. PAT甲级题分类汇编——理论

    本文为PAT甲级分类汇编系列文章. 理论这一类,是让我觉得特别尴尬的题,纯粹是为了考数据结构而考数据结构.看那Author一栏清一色的某老师,就知道教数据结构的老师的思路就是和别人不一样. 题号 标题 ...

  8. nohup 命令

    nohup command > myout.file 2>&1 & 指定nohup.out的文件名 jobs -l 查看后台命令

  9. 【LEETCODE】34、119题,Pascal's Triangle II

    package y2019.Algorithm.array; import java.util.ArrayList; import java.util.List; /** * @ProjectName ...

  10. [Done] Codeforces Round #562 (Div. 2) 题解

    A - Circle Metro 模拟几百步就可以了. B - Pairs 爆搜一下,时间复杂度大概是 $O(4 * n)$ Code: 56306723 C - Increasing by Modu ...