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点的所有路径中,最长的边最小值是多少?

输出

对每个询问,输出最长的边最小值是多少。

样例输入

6 6 8
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
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,最小生成树的更多相关文章

  1. BZOJ3732Network——kruskal重构树+倍增+LCA/最小生成树+倍增

    题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...

  2. LCA&最小生成树

    LCA 经常被用来使用.比如询问树两点之间的距离. 比如树上差分 都是经常被使用的类型.有的时候倍增求LCA的同时还可以优化算法. 这道题呢 求一个严格的最小生成树,当然如果不严格的话如果有重边那么就 ...

  3. uva11354 LCA+最小生成树+dp

    源自大白书 题意 有n座城市通过m条双向道路相连,每条道路都有一个危险系数.你的任务是回答若干个询问,每个询问包含一个起点s和一个终点t,要求找到一条从s到t的路,使得途径所有的边的大最大危险系数最小 ...

  4. The Shortest Statement(Educational Codeforces Round 51 (Rated for Div.2)+最短路+LCA+最小生成树)

    题目链接 传送门 题面 题意 给你一张有\(n\)个点\(m\)条边的联通图(其中\(m\leq n+20)\),\(q\)次查询,每次询问\(u\)与\(v\)之间的最短路. 思路 由于边数最多只比 ...

  5. 洛谷 P1967 货车运输 LCA + 最小生成树

    两点之间边权最大值的最小值一定在图的最小生成树中取到. 求出最小生成树,进行倍增即可. Code: #include<cstdio> #include<algorithm> u ...

  6. OpenJudge 2990:符号三角形 解析报告

    2990:符号三角形 总时间限制:  1000ms       内存限制:  65536kB 描述 符号三角形的第1行有n个由“+”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”+“ ...

  7. BZOJ1088扫雷Mine 解析报告

    1088: [SCOI2005]扫雷Mine Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的扫 ...

  8. OpenJudge 2985数字组合 解析报告/DP

    2985:数字组合 总时间限制:  1000ms 内存限制:  65536kB 描述 有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式.如:n=5,5个数分别为1,2,3,4,5,t=5: ...

  9. openjudge7834:分成互质组 解析报告

    7834:分成互质组 总时间限制:  1000ms 内存限制:  65536kB 描述 给定n个正整数,将它们分组,使得每组中任意两个数互质.至少要分成多少个组? 输入 第一行是一个正整数n.1 &l ...

随机推荐

  1. 机器学习编程语言之争,Python 夺魁【转载+整理】

    原文地址 en cn 本文内容 表现平平的 MATLAB 貌似强大的 Julia 本身无错的 R 语言 逐渐没落的 Perl 老而弥坚的 Python 我个人很喜欢 Python~ 随着科技的发展,拥 ...

  2. mysql in 排序

    SELECT * FROM my_table WHERE id IN (30, 20, 80, 40) ORDER BY FIELD(id, 30, 20, 80, 40);

  3. GOOGLE不能访问的解决方法

    1VPN gate 2自 由 门 3修改Windows\System32\drivers\etc hosts (复制https://github.com/txthinking/google-hosts ...

  4. sonar的安装与代码质量检测实例

    说明:sonar依赖数据库. mysql优化 1.笔者使用的是mysql数据库.首先对mysql做简单的优化配置. [root@localhost bin]# cat /etc/my.cnf [mys ...

  5. Azure SoftEther VPN

    装个vs2015,想装全组建还得爬墙… 曾经的 Azure OpenVPN 项目 (http://azure-openvpn.github.io/) 好几年木有更新 改用 SoftEther VPN ...

  6. 【转帖】四种BI 开源工具介绍-SpagoBI,openI,JasperSoft,Pentaho

    四种BI 开源工具介绍-SpagoBI,openI,JasperSoft,Pentaho 1 BI系统的简述 从技术角度来说 BI 包含了 ETL.DW.OLAP.DM等多环节.简单的说就是把交易系统 ...

  7. 让Mac也能拥有apt-get类似的功能——Brew

    之前一直怀念ubuntu下的apt-get,因为实在是方便,需要安装什么,一个命令搞定,相关的依赖包统统由apt-get维护.下载,编译,安装,那叫一个痛快.什么软件用着不爽,一个命令卸载! 怀念ap ...

  8. .NET Framework 类库

    .NET Framework 类库 MSDN == V2.0 == .NET Framework 类库是一个由 Microsoft .NET Framework SDK 中包含的类.接口和值类型组成的 ...

  9. Eclipse中如何修改SVN的地址

    在SVN服务端的IP更改后,客户端SVN的连接地址可以在Eclipse中进行修改,方法如下: 首先:在Eclipse中选择Windows-> Show View->others 就会出现[ ...

  10. Canvas现实画板功能

    先看图片 HTML <!doctype html> <html lang="en"> <head> <meta charset=" ...