BZOJ3732 解析报告//LCA,最小生成树
3732: Network
题目描述
给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).
现在有 K个询问 (1 < = K < = 15,000)。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
输入
第一行: N, M, K。
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
输出
对每个询问,输出最长的边最小值是多少。
样例输入
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
样例输出
5
5
4
4
7
4
5
提示
1 <= N <= 15,000 1 <= M <= 30,000 1 <= d_j <= 1,000,000,000 1 <= K <= 15,000
分析:
拿到这道题我们会有思考。什么是最长的边的最小值。这也正是这道题的突破口。在一个图中任意两点都有很多条路,我们要找出其中一条路,使这条路上的最大的权值是其他路上最大权值中最小的。而我们要保证权值最小,但是还是当前路上最大。由于这里没有限制边数,我们会想到。树上的一个有趣的模型——最小生成树。这棵树上每条路都是整个图中较小的边,而我们的问题就转化成了在最小生成树上找最大边。这个时候就可以用倍增的思想找LCA。在一棵树上两点之间最短距离一定经过它们的LCA。所以我们找出2点的LCA而且维护这条最短路径上的最大边即可。
为什么两点之间的最长边的最小值一定在这个图上的最小生成树上呢?
假设我们有一个这样的无向图。
1,这是一个很普通的无向图。首先我们先找出它的最小生成树。一种贪婪策略。嗯就是这样。
2,其次我们找3号点和4号点中最长边的最大值是2.这个边在最小生成树上。
3,我们假设一个边4-3这条边的权值假设成1.而我们发现当这个边权都比最小生成树上的边的权值还小,说明这条边一定在最小生成树上。如图所示。
所以:这道题其实就是。首先,建最小生成树,其次找LCA维护最值。之后。提交。AC。
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
struct node{
int x,y,val;
}point[100010];
struct node_1{
int num,minval;
}f[21][100010];
struct node_2{
int v,next,val;
}edge[1000010];
int head[1000010],cnt;
int cmp(node a,node b)
{
return a.val<b.val;
}
int visit[100010],father[100010],n,m,q,dep[100000];
int find_father(int x)
{
return father[x]==x ? x : father[x]=find_father(father[x]);
}
void add(int x,int y,int val)
{
edge[++cnt]=(node_2){y,head[x],val};
head[x]=cnt;
edge[++cnt]=(node_2){x,head[y],val};
head[y]=cnt;
return ;
}
void dfs(int x,int step)
{
visit[x]=1;
dep[x]=step;
for(int i=head[x];i!=-1;i=edge[i].next)
{
if(visit[edge[i].v])continue;
f[0][edge[i].v].num=x;
f[0][edge[i].v].minval=edge[i].val;
dfs(edge[i].v,step+1);
}
return ;
}
int LCA(int x,int y)
{
int lca=-1;
if(dep[x]>dep[y])swap(x,y);
for(int i=20;~i;--i)
{
if(dep[f[i][y].num]>=dep[x])
{
lca=max(lca,f[i][y].minval);
y=f[i][y].num;
}
}
if(x==y)return lca;
for(int i=20;~i;--i)
{
if(f[i][y].num!=f[i][x].num)
{
lca=max(lca,max(f[i][y].minval,f[i][x].minval));
y=f[i][y].num;
x=f[i][x].num;
}
}
lca=max(lca,max(f[0][y].minval,f[0][x].minval));
return lca;
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&q);
int a,b,c;
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&a,&b,&c);
point[i].x=a;point[i].y=b;point[i].val=c;
}
sort(point+1,point+1+m,cmp);
int cnt_1=0;
for(int i=1;i<=n;++i)father[i]=i;
for(int i=1;i<=m;++i)
{
int la = find_father(point[i].x),lb = find_father(point[i].y);
if(la!=lb)
{
father[lb]=la;
add(point[i].x,point[i].y,point[i].val);
++cnt_1;
}
if(cnt_1==n-1)break;
}
f[0][cnt_1/2].num=cnt_1/2;f[0][cnt_1/2].minval=0;
dfs(cnt_1/2,1);
for(int i=1;i<=20;++i)
for(int j=1;j<=n;++j)
{
f[i][j].minval=max(f[i-1][j].minval,f[i-1][f[i-1][j].num].minval);
f[i][j].num=f[i-1][f[i-1][j].num].num;
}
for(int i=1;i<=q;++i)
{
scanf("%d%d",&a,&b);
printf("%d\n",LCA(a,b));
}
return 0;
}
嗯。就是这样。
BZOJ3732 解析报告//LCA,最小生成树的更多相关文章
- BZOJ3732Network——kruskal重构树+倍增+LCA/最小生成树+倍增
题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...
- LCA&最小生成树
LCA 经常被用来使用.比如询问树两点之间的距离. 比如树上差分 都是经常被使用的类型.有的时候倍增求LCA的同时还可以优化算法. 这道题呢 求一个严格的最小生成树,当然如果不严格的话如果有重边那么就 ...
- uva11354 LCA+最小生成树+dp
源自大白书 题意 有n座城市通过m条双向道路相连,每条道路都有一个危险系数.你的任务是回答若干个询问,每个询问包含一个起点s和一个终点t,要求找到一条从s到t的路,使得途径所有的边的大最大危险系数最小 ...
- The Shortest Statement(Educational Codeforces Round 51 (Rated for Div.2)+最短路+LCA+最小生成树)
题目链接 传送门 题面 题意 给你一张有\(n\)个点\(m\)条边的联通图(其中\(m\leq n+20)\),\(q\)次查询,每次询问\(u\)与\(v\)之间的最短路. 思路 由于边数最多只比 ...
- 洛谷 P1967 货车运输 LCA + 最小生成树
两点之间边权最大值的最小值一定在图的最小生成树中取到. 求出最小生成树,进行倍增即可. Code: #include<cstdio> #include<algorithm> u ...
- OpenJudge 2990:符号三角形 解析报告
2990:符号三角形 总时间限制: 1000ms 内存限制: 65536kB 描述 符号三角形的第1行有n个由“+”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”+“ ...
- BZOJ1088扫雷Mine 解析报告
1088: [SCOI2005]扫雷Mine Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的扫 ...
- OpenJudge 2985数字组合 解析报告/DP
2985:数字组合 总时间限制: 1000ms 内存限制: 65536kB 描述 有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式.如:n=5,5个数分别为1,2,3,4,5,t=5: ...
- openjudge7834:分成互质组 解析报告
7834:分成互质组 总时间限制: 1000ms 内存限制: 65536kB 描述 给定n个正整数,将它们分组,使得每组中任意两个数互质.至少要分成多少个组? 输入 第一行是一个正整数n.1 &l ...
随机推荐
- shell变量注意事项
概念:变量赋值,变量替换,变量引用,命令替换 variable=22 echo variable 可以在同一行设置多个变量.例如 va1=good va2=chif va3=beijing #需 ...
- 曲率已驱动了头发——深度分析谷歌AlphaGo击败职业棋手
这篇是我们自开设星际随笔以来写得最长的一篇.我们也花了不少力气.包括把那5盘棋各打了两遍的谱,包括从Nature官网上把那篇谷歌的报告花了200元下载下来研究它的算法(后来发现谷 歌网站上可以免费下载 ...
- S7-200系列PLC与WINCC以太网通信CP243i的实例
S7-200系列PLC与WINCC以太网通信CP243i的实例 ----选用大连德嘉国际电子www.dl-winbest.cn的CP243i作为连接S7-200的PPI口转以太网RJ45的接口转换器. ...
- 求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。
import java.util.Scanner; /** * 题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字. * 2+22+222+2222+22222(此时共有5个数 ...
- GNU Radio 之 rtl-sdr
http://sdr.osmocom.org/trac/wiki/rtl-sdr 我使用的是去年买的一个电视棒(ezcap DVB-TFMDAB),50多元,它的频宽为52Mhz - 2.2GHz ! ...
- whoami 和 Who am i
① 两个命令在一般的情况下,似乎效果是一样的 ② 但是当你执行完su 命令切换用户后,就不一样了,who am i 显示最早login的账户,而whoami 显示切换后的账户 例如: -bash-3. ...
- Tomcat抛出异常:ClientAbortException: java.net.SocketException: Connection
在做一个小网站的时候,写了一个通过servlet实现文件下载功能的页面.当我点击超级练级,弹出下载对话框,点击保存正常下载,不会出现任何问题,当我我点击取消,服务器端就出现如下提示: ClientAb ...
- 温故而知新:Delegate,Action,Func,匿名方法,匿名委托,事件
Tks: http://www.cnblogs.com/yjmyzz/archive/2009/11/23/1608818.html 20150801 add: http://www.cnblogs. ...
- 针对 SQL Server 2008 在Windows Server 2008上的访问配置 Windows 防火墙
现在Windows Server 2008 服务器用的越来越多,2008的防火墙比2003的有了很大的增强,安全性有了更大的提高. 甚至80端口的出站默认都是被关闭的.所以如果在2008Server上 ...
- 构建基于WinRT的WP8.1 App 03:Page控件
单页面模板 通常利用Visual Studio 2013创建的最简单的WP8.1应用是Blank App,它只包含一个不带任何UI的页面,并且没有任何状态管理的逻辑. 该不带任何UI的页面称为Blan ...