BZOJ3732 解析报告//LCA,最小生成树

news/2024/7/4 8:42:46

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而且维护这条最短路径上的最大边即可。

为什么两点之间的最长边的最小值一定在这个图上的最小生成树上呢?

假设我们有一个这样的无向图。

123

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;
}

嗯。就是这样。

转载于:https://www.cnblogs.com/uncle-lu/p/5948809.html


http://www.niftyadmin.cn/n/1808725.html

相关文章

java语句输出0-9_【视频+图文】Java经典基础练习题(二)输出9*9乘法口诀表

能解决题目的代码并不是一次就可以写好的我们需要根据我们的思路写出后通过debug模式找到不足再进行更改多次测试后才可得到能解决题目的代码&#xff01;通过学习&#xff0c;练习【Java基础经典练习题】让我们一起来培养这种解决问题思路。一、视频讲解二、思路分析Q1&#x…

BOS物流项目笔记(11)

1、学习计划 &#xff08;1&#xff09;在realm中进行授权 &#xff08;2&#xff09;使用shiro的方法注解方式权限控制 在spring文件中配置开启shiro注解支持 在Action方法上使用注解 &#xff08;3&#xff09;使用shiro的标签进行权限控制 在页面引入shiro的标签库 在页…

BLOG搬家了,新家地址http://changeself.com,改变网!

感谢大家多年的支持&#xff0c;感谢CSDN的支持&#xff0c;跟很多老人一样&#xff0c;实在是无奈&#xff0c;必须自己搞一个独立的站点来继续经营自己的博客&#xff1b; 新家地址&#xff1a;http://changeself.com&#xff0c;这个域名我5年前就买下了&#xff0c;今天终…

Python标准库11 多进程探索 (multiprocessing包)

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01; 在初步了解Python多进程之后&#xff0c;我们可以继续探索multiprocessing包中更加高级的工具。这些工具可以让我们更加便利地实现多进程。 进程…

专业程序员的7个特质

专业程序员的7个特质 成为一个专业人士是所有程序员的目标。笔者在硅谷待了将近3年&#xff0c;在这里近距离观察了Google, Facebook, Uber等公司的大拿&#xff0c;并有幸与其中的一部分一起工作。在此分享大牛程序员的行为风格以及我自己的所思所想&#xff0c;希望对大家有所…

java list 底层构建_Java基础进阶 集合框架详解

今日任务1、List接口介绍(掌握常用List特有方法)2、练习3、ArrayList介绍(必须清楚集合的特征、掌握集合中的方法)4、LinkedList介绍(必须清楚集合的特征、掌握集合中的方法)5、Vector 类介绍(了解)6、List下的子类总结(掌握)7、Set 接口介绍(掌握Set集合的特性)8、HashSet 集合…

Tahiti: Voices of Paradise 专辑中文名: 大溪地:天堂之声

专辑英文名: Tahiti: Voices of Paradise 专辑中文名: 大溪地&#xff1a;天堂之声 艺术家: Dan Gibson 资源格式: MP3 发行时间: 2008年07月01日 地区: 加拿大 简介: 发行公司&#xff1a;Solitudes 音乐风格&#xff1a;New Age, World 专辑介绍&#xff1a; Dan Gibson此次…

JavaWeb总结(五)

使用Servlet接受服务器请求信息 HTTP请求示例 HttpServletRequest对象主要用于获取由客户端发送过来的请求头、参数、文件、数据等。Servlet存在的主要目的就是处理请求。Servlet规范中对此对象进行了增强&#xff0c;使其还可以与Web应用程序交互 GET/POST提交方法 - 浏览器向…