NOIP 2013 P1967 货车运输
倍增求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 货车运输的更多相关文章
- [Noip 2013 Day1-3] 货车运输 做法总结
[Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...
- 「NOIP 2013」 货车运输
题目链接 戳我 \(Solution\) 这一道题直接用\(kruskal\)重构树就好了,这里就不详细解释\(kruskal\)重构树了,如果不会直接去网上搜就好了.接下来讲讲详细过程. 首先构建\ ...
- 洛谷 P1967 货车运输
洛谷 P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在 ...
- P1967 货车运输
P1967 货车运输最大生成树+lca+并查集 #include<iostream> #include<cstdio> #include<queue> #inclu ...
- 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增
倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...
- Luogu P1967 货车运输(Kruskal重构树)
P1967 货车运输 题面 题目描述 \(A\) 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\) ,城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 \ ...
- 【杂题总汇】NOIP2013(洛谷P1967) 货车运输
[洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...
- NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)
题目: A 国有 nn 座城市,编号从 11 到 nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情 ...
- 洛谷 P1967 货车运输(克鲁斯卡尔重构树)
题目描述 AAA国有nn n座城市,编号从 11 1到n nn,城市之间有 mmm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qqq 辆货车在运输货物, 司机们想知道每辆车在不超过车 ...
随机推荐
- Code Test(2)
1110test T1:Inversion逆序数对1(inversion.cpp/in/out 1s 256M)给定N的值,要求找出一个N的全排列,这个全排列中,逆序数有M对.这样的结果会存在多个解, ...
- 076 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 01 Java面向对象导学
076 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 01 Java面向对象导学 本文知识点:Java面向对象导学 说明:因为时间紧张,本人 ...
- Java知识系统回顾整理01基础05控制流程07结束外部循环
一.break是结束当前循环 二.结束当前循环实例 break; 只能结束当前循环 public class HelloWorld { public static void main(String[] ...
- AD(Altium Designer)PCB布线中的“格式刷”,助力快速布局布线
摘要:在AD(Altium Designer)进行电路板布线时,孔丙火(微信公众号:孔丙火)经常会碰到电路中有相同功能的模块,比如2路相同的RS485通信电路.多路相同继电器输出电路.多路相同的输入电 ...
- MeteoInfoLab脚本示例:计算垂直螺旋度
尝试编写MeteoInfoLab脚本计算垂直螺旋度,结果未经验证. 脚本程序: print 'Open data files...' f_uwnd = addfile('D:/Temp/nc/uwnd ...
- day06 Pyhton学习
一.昨日内容回顾 字典: 由{}表示,内部存储key:value 要求: key不能重复 key必须可哈希.不可变 value没有限制 没有索引和切片 增删改查 新增: dic.[新key]=valu ...
- Jenkins环境搭建(7)-集成钉钉消息推送
在去年的时候,搭建了一套Jenkins环境,基本功能已实现,可以通过如下地址查阅. Jenkins环境搭建(1)-下载与安装 Jenkins环境搭建(2)-搭建jmeter+ant+jenkins自动 ...
- vm虚拟机设置共享文件夹不显示
1. 确认VMtools已经装好,开启共享文件夹,设置好共享目录 2.执行命令 sudo mount -t vmhgfs .host:/ /mnt/hgfs如果出现错误: Error: cannot ...
- lumen-ioc容器测试 (1)
lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...
- Excel中外部数据链接无法删除的解决方法【转】
[摘要] 当Excel中公式引用了外部数据,每次打开时,总是自动弹出自动更新链接的对话框.如何找到这些链接?有没有办法实现断开原有链接,而保持数值不变? 有客户反应,当Excel无法链接到外部数据后, ...