倍增求LCA+最大生成树

题目给出的是一张图,在图上有很多算法无法实现,所以要将其转化为树

题中可以发现货车的最后的载重量是由权值最小的一条边决定的,所以我们求最大生成树

求完最大生成树后我们得到一个森林

现在转化为了求两点路径经过边的边权的最小值,用倍增算法进行计算

#include <bits/stdc++.h>
#define inf 1e9
using namespace std;
const int MAXN=10100;
int n,m,first[MAXN],nxt[MAXN*10],point[MAXN*10],len[MAXN*10];
int q,tot,fa[MAXN],f[MAXN][21],chmin[MAXN][21],vi[MAXN],de[MAXN];
struct node
{
int u,v,len;
}sh[MAXN*5];
void add_edge(int x,int y,int z)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
point[tot]=y;
len[tot]=z;
}
void dfs(int x,int father,int deep,int last,int visit)
{
de[x]=deep;
vi[x]=visit;
f[x][0]=father;//倍增father数组
chmin[x][0]=last;//记录上一条边的权值
for (int i=first[x];i!=-1;i=nxt[i])
{
if (point[i]!=father)
{
dfs(point[i],x,deep+1,len[i],visit);
}
}
}
int getfather(int x)
{
if (fa[x]==x)
return fa[x];
fa[x]=getfather(fa[x]);
return fa[x];
}
bool cmp(node a,node b)
{
return a.len>b.len;
}
int lca(int a,int b)//倍增求LCA
{
if (getfather(a)!=getfather(b))
return -1;
if (de[a]>de[b])
swap(a,b);
int MIN=inf;
for (int i=20;i>=0;i--)
{
if (de[f[b][i]]>=de[a])
{
MIN=min(MIN,chmin[b][i]);
b=f[b][i];
}
}
if (a==b)
return MIN;
for (int i=20;i>=0;i--)
{
if (f[a][i]!=f[b][i])
{
MIN=min(MIN,min(chmin[a][i],chmin[b][i]));
a=f[a][i];
b=f[b][i];
}
}
MIN=min(MIN,min(chmin[a][0],chmin[b][0]));
return MIN;
}
int main()
{
tot=-1;
memset(nxt,-1,sizeof(nxt));
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&sh[i].u,&sh[i].v,&sh[i].len);
}
for (int i=1;i<=n;i++)
fa[i]=i;
sort(sh+1,sh+1+m,cmp);
for (int i=1;i<=m;i++)
{
if (getfather(sh[i].u)!=getfather(sh[i].v))
{
fa[getfather(sh[i].u)]=getfather(sh[i].v);
add_edge(sh[i].u,sh[i].v,sh[i].len);
add_edge(sh[i].v,sh[i].u,sh[i].len);
}
}//求最大生成树
int now=0;
for (int i=1;i<=n;i++)//可能有多棵树,每棵树分别考虑
{
if (vi[i]!=0)
continue;
now++;
dfs(i,0,0,inf,now);
f[i][0]=i;
chmin[i][0]=inf;
}
for (int j=1;j<=20;j++)
{
for (int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
chmin[i][j]=min(chmin[i][j-1],chmin[f[i][j-1]][j-1]);//进行倍增
}
}
scanf("%d",&q);
for (int i=1;i<=q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
}

倍增求LCA时避免父亲倍增数组出现0,倍增记录最小值时,简单写法

    int now=0;
for (int i=1;i<=n;i++)
{
if (vi[i]!=0)
continue;
now++;
dfs(i,0,0,inf,now);
f[i][0]=i;//使当前的father==i
chmin[i][0]=inf;//记录的最小值
}

求deep时,注意不是求距离上的deep,而是层数

void dfs(int x,int father,int deep,int last,int visit)
{
de[x]=deep;
vi[x]=visit;
f[x][0]=father;
chmin[x][0]=last;
for (int i=first[x];i!=-1;i=nxt[i])
{
if (point[i]!=father)
{
dfs(point[i],x,deep+1,len[i],visit);//deep是+1,不是加len[i],注意
}
}
}

NOIP 2013 P1967 货车运输的更多相关文章

  1. [Noip 2013 Day1-3] 货车运输 做法总结

    [Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...

  2. 「NOIP 2013」 货车运输

    题目链接 戳我 \(Solution\) 这一道题直接用\(kruskal\)重构树就好了,这里就不详细解释\(kruskal\)重构树了,如果不会直接去网上搜就好了.接下来讲讲详细过程. 首先构建\ ...

  3. 洛谷 P1967 货车运输

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

  4. P1967 货车运输

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

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

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

  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. NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)

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

  9. 洛谷 P1967 货车运输(克鲁斯卡尔重构树)

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

随机推荐

  1. 下载、安装 PL/SQL Developer

    操作系统:Windows 10 x64 第一节:下载 Oracle Database XE 11gR2 第二节:安装.验证安装 Oracle Database XE 11gR2 第三节:Oracle ...

  2. ansible-playbook通过github拉取部署Lnmp环境

    1. 配置服务器初始化  1.1) 关闭防火墙和selinux 1 [root@test-1 ~]# /bin/systemctl stop firewalld 2 [root@test-1 ~]# ...

  3. iOS使用NSTextAttachment添加图片,图片模糊

    最近在忙的项目中,需要处理富文本的相关内容,产品需求并不复杂,所以想着用TextKit处理,顺便学习一下,没想到直接掉坑.在此记录一下(都是血泪史),顺便为有需要的小伙伴提供参考. // Add th ...

  4. 警惕char类型直接相加

    今天在写某个程序需要对两个数字字符串进行相加操作,比如字符串1:12345,字符串2:23456.需要1和2相加.2和3相加.就是两个字符相同位置的数进行相加. 这个一看很好完成,写一个for,然后取 ...

  5. golang Gin framework with websocket

    概述 golang websocket 库 示例 后端 前端 结论 概述 对于 golang 的 web 开发, 之前写过 2 篇 blog, 分别介绍了: 在 Gin 框架下, 各类 http AP ...

  6. 多测师讲解selenium _assert断言_高级讲师肖sir

    assert断言 # # 断言:最常用的断言方法if判断# assert Python语法中自带的断言from selenium import webdriverfrom time import sl ...

  7. vs code个性化设置

    文件=>首选项=>设置,直接在搜索栏搜索有背景色的部分即可 1. 鼠标滚轮缩放 "editor.mouseWheelZoom": true 2. 显示空格和tab符号 ...

  8. MeteoInfoLab脚本示例:中文处理

    在脚本中使用中文需要指明是unicode编码,即在含有中文的字符串前加u,比如:u'中文'.还需要将字体指定为一种中文字体.详见下面的例子.脚本程序: x = [1,2,3,4] y = [1,4,9 ...

  9. [leetcode] 剑指 Offer 专题(一)

    又开了一个笔记专题的坑,未来一两周希望能把<剑指Offer>的题目刷完

  10. Lock、Synchronized锁区别解析

    上篇博文在讲解 ConcurrentHashMap 时说到 1.7 中 put 方法实现同步的方式是使用继承了 ReentrantLock 类的 segment 内部类调用 lock 方法实现的,而在 ...