倍增求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. Arduino 串口的一些高级用法

    来源: 1.配置串口通信数据位.校验位.停止位 通常我们使用Serial.begin(speed)来完成串口的初始化,这种方式,只能配置串口的波特率. 而使用Serial.begin(speed, c ...

  2. 为自己的网页博客添加L2Dwidget.js看板娘

    如果是博客园,直接在设置-->页脚 HTML 代码,加上下面代码: 1 <!-- L2Dwidget.js L2D网页动画人物 --> 2 <script src=" ...

  3. JavaScript按钮排他思想

    要求: 有一系列按钮,要求每单击其中一个,该按钮改变样式(以背景颜色为例),其他按钮恢复保持默认样式. 实现思路: 获取所有按钮元素 首先先把其他按钮的背景颜色去掉 再单独设置自己的样式 代码实现: ...

  4. Jenkins从节点上构建自动化测试项目时报错:java.io.IOException: Unexpected termination of the channel

    在mac电脑上配置了Jenkins从节点,在该从节点上构建app UI 自动化测试项目,运行一些用例后报如下错误: java.io.EOFException at java.io.ObjectInpu ...

  5. 多测师讲解requests __上_高级讲师肖sir

    1.三种接口接口请求方式 # # 在python当中接口的请求方式有哪些:# import requests # 导入requests接口库# # # # 请求方式有三种:# # # # 第一种:# ...

  6. C 和 C++ 打起来了!曾今最亲密的伙伴到现今的不爽?

    70年代初,贝尔实验室创建了C语言,它是开发UNIX的副产品.很快C就成为了最受欢迎的编程语言之一.但是对于Bjarne Stroustrup来说,C的表达能力还不够.于是,他在1983年的博士论文中 ...

  7. oh my zsh 常用插件

    date: "2020-10-18T12:36:00+08:00" title: "oh my zsh 常用插件" tags: ["zsh" ...

  8. Docker安装以及运行第一个HelloWorld

      Docker安装以及运行第一个HelloWorld

  9. go正则贴吧

    package main import ( "fmt" "io/ioutil" "net/http" "regexp" ...

  10. spring boot:用swagger3生成接口文档,支持全局通用参数(swagger 3.0.0 / spring boot 2.3.2)

    一,什么是swagger? 1,  Swagger 是一个规范和完整的文档框架, 用于生成.描述.调用和可视化 RESTful 风格的 Web 服务文档 官方网站: https://swagger.i ...