倍增求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. 学习git这一篇就够了!!!

    git命令操作 本地库操作 初始化本地仓库 初始化命令 git init $ work % cd workspace $ workspace % mkdir WebService //创建文件夹 $ ...

  2. matlab中repmat函数的用法

    转载:https://blog.csdn.net/facetosea1/article/details/83573859 B = repmat(A,m,n)B = repmat(A,[m n])B = ...

  3. K8S-kubeadm-集群证书续签

    ETCD证书 自签证书颁发机构(CA) ca.crt ca.key etcd集群中相互通信事业的客户端证书 peer.crt peer.key pod中定义Liveness探针事业的客户端证书 hea ...

  4. ansible-主机清单的配置

    1. ansible主机清单的配置 以下是ansible安装完成后的源文件 1 [root@test-1 ~]# cat /etc/ansible/hosts 2 # This is the defa ...

  5. 技术分享丨华为鲲鹏架构Redis知识二三事

    摘要:华为云鲲鹏Redis,业界首个基于自研ARM-Based全栈整合的Redis云服务,支持双机热备的HA架构,提供单机.主备.Proxy集群.Cluster集群实例类型,满足高读写性能场景及弹性变 ...

  6. layui+tp5表单提交回调

    layui 前段页面form表单提交数据如果监听表单提交 ,tp5后台操作完成后使用 $this->success('success'); 后前端的页面不会出现layui的layer弹窗提示su ...

  7. 3.字符设备led驱动

    1.硬件原理图 由图可知,led1,led2,led3,led4,分别对应GPB5,GPB6,GPB7,GPB8,由s3c2440芯片手册可得到如下图所示,分别配置GPBCON和GPBDAT即可 2. ...

  8. 租房数据分析,knn算法使用

    import numpy as np import pandas as pd import matplotlib.pyplot as plt data = pd.read_excel('jiemo.x ...

  9. k8s-命令创建service

    查看命令帮助 [root@master kubernetes]# kubectl create service -h Create a service using specified subcomma ...

  10. SQL报表语句;SQL获取今日、本周、本月数据

    SQL报表语句     SQL获取今日.本周.本月数据 本日:select * from table where datediff(dd,C_CALLTIME,getdate())=0     --C ...