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. windows7文件共享

    工作组模式下: 参考:http://support.microsoft.com/kb/2533010/zh-cn 1.首先区分网络类型配置文件:家庭网络,工作网络还是公用网络 2.每种类型区分两种文件 ...

  2. 高级屏幕空间反射: Screen Space Reflection (SSR)

    自从CE3首倡SSR以来,发展至今,其质量与当年早已不能同日而语.不仅强调超越性的质量,而且强调超越性的性能.乘着周末有空撸了撸,以下是增强型实时SSR结果图.与我原来的SSR原始实现相比,新的增强型 ...

  3. Git教程学习(五)

    14. 解决冲突 14.1. 场景 当分支A和分支B在同一个文件上都有修改时会出现冲突.常见的情况是从master分支的基础上生成了新分支dev,然后在dev上进行了修改并add&commit ...

  4. [数据库]SQL Server 用户NT AUTHORITY\IUSR 登录失败

    今天打开网站时,突然报这个错误,平时都好好的 Cannot open database "JMECC" requested by the login. The login fail ...

  5. asp.net 多个文件同时下载

    1.首先读取文件夹下的文件,可能同时存在多个文件 2.选中文件,然后点击下载,同时可以选择多个文件. 思路:通过生产压缩包的形式进行下载,然后再清楚压缩包,这样用户可以一次性全部下载下来. 一.获取目 ...

  6. 1.什么是泛型和C#中泛型在Class上的实现

    阅读目录 一:什么是泛型? 二:C#中泛型在Class上的实现   一:什么是泛型? 我们在编程的时候需要一个数据类型,但是在刚开始的时候还不确定这个数据类型是怎么样的,或者说对于不同的多个数据类型有 ...

  7. Linux下配置ip地址四种方法

    linux系统安装完,以后通过命令模式配置网卡IP.配置文件通常是/etc/sysconfig/network-scripts/ifcfg-interface-nameifconfig后显示的内容,l ...

  8. Openvswitch原理与代码分析(8): 修改Openvswitch代码添加自定义action

    有时候我们需要自定义一些自己的action,根据包头里面的信息,做一些自己的操作.   例如添加一个action名为handle_example   第一.修改ofp-actions.c文件   首先 ...

  9. Hadoop - Kylin On OLAP

    1.概述 Apache Kylin是一个开源的分布式分析引擎,提供SQL接口并且用于OLAP业务于Hadoop的大数据集上,该项目由eBay贡献于Apache. 2.What is Kylin 在使用 ...

  10. preg_match_all正则表达式的基本使用

    了解正则表达式之前,须要掌握一些常用的正则表达式的基础知识,这些如果能记得最好记得,记不住须要用的时候能查到就行,就多个特殊字符,所以说正则表达式玩的就是特殊,具体大家可以查看更加细致的说明. pre ...