倍增求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. C++ CComboBox控件详解

    转载:http://blog.sina.com.cn/s/blog_46d93f190100m395.html C++ CComboBox控件详解 (2010-09-14 14:03:44) 转载▼ ...

  2. CentOS 7安装docker和常用指令

    1.安装 yum -y install docker 2.启动 systemctl start docker // 启动 docker -v //查看版本号 systemctl stop docker ...

  3. [WC 2011]最大Xor和路径

    题目大意: 给你一张n个点,m条边的无向图,每条边都有一个权值,求:1到n的路径权值和的最大值. 题解: 任意一条路径都能够由一条简单路径(任意一条),在接上若干个环构成(如果不与这条简单路径相连就走 ...

  4. Visual C# 制作DLL文件

    一.制作.dll1.首先创建一个新类库工程文件  文件->新建->项目->Visual C#->类库.填入工程文件名称,并且选择文件要存放的目录. 2.工程文件 将Class1 ...

  5. lua 1.0 源码分析 -- 2 内存回收

    说这个,先要说下 lua 的环境,正常说创建一个 lua 的虚拟环境,就是创建一组全局变量, lua1.0 里创建的主要是以下几个: extern Symbol *lua_table; /* 符号数组 ...

  6. 2014年 实验二 B2C网上购物

    实验二 B2C网上购物 [实验目的] ⑴.熟悉虚拟银行和网上支付的应用 ⑵.熟悉并掌握消费者B2C网上购物和商家的销售处理 [实验条件] ⑴.个人计算机一台 ⑵.计算机通过局域网形式接入互联网 (3) ...

  7. HTML常用标签(下)

    HTML常用标签(下) 1. 表格标签 1.1 语法 <table> <!--table定义表格--> <tr> <!--tr定义表格中的行--> &l ...

  8. h5的第一份翻译

    <!DOCTYPE html>DOCTYPE DOC文本文档documentTYPE 类型html hyper超,超级的:text文本:markup标记:language语言<htm ...

  9. day54 Pyhton 前端JS06

    内容回顾 - ECMAScript5.0 基础语法 - var 声明变量 - 五种基本数据类型 - string - number NaN number 1 number - boolean - un ...

  10. C++11随机数库

    random随机数库 C++11引入了新的随机数生成机制,那就是<random>随机数库,支持多种伪随机数生成算法,多种连续和离散随机数分布算法,以及封装了真正的随机数生成引擎random ...