!!!原来LCA的题可以出的这么难,完了这还属于水题?!

先来解释一下题意,有N个城市,在这N城市之间有M条边(不一定每个城市都有边)。我们的任务是找出给定两个点之间路径上的最小边权,使得这个最小边权尽量大。一开始我很纳闷,这和LCA有什么关系呢,怎么和最大流有点像。冥思苦想(看了别人的想法)之后,哦,原来是最大生成树+LCA。。。因为是最大生成树,可以使得任意两点间路径上的最大边权最大(再连上较小的会成环)。这样问题就变成了找树上两点间路径上的最小边权,显然可以利用LCA,这是他十分经典的应用。设minn[i][j]表示从结点i向上蹦2^j次,中间路径上的最小边权,则minn[i][0]=w<father[i],i>(从其父亲到结点i的边权),minn[i][j]=min(minn[i][j-1],minn[fa[i][j-1]][j-1])(j!=0),相当于将路径二分。

这道题最纠结的在于一开始建树的过程,是用Kruskal没有疑问,但是真的是建无向图吗?树根怎么确定?修改了好久才弄对,代码及其。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e4+5,maxm=5e4+5;
int n,m,head[maxn],eid;
struct edge {int u,v,w;bool operator < (const edge& rhs) const {return w>rhs.w;}
} E[maxm];
struct edge2 {int v,w,next;
} e[2*maxn];
void insert(int u,int v,int w) {e[eid].v=v,e[eid].w=w;e[eid].next=head[u];head[u]=eid++;
}
int dj_fa[maxn];
int dj_find(int i) {if(i==dj_fa[i]) return i;return dj_fa[i]=dj_find(dj_fa[i]);
}
void dj_merge(int a,int b) {a=dj_find(a),b=dj_find(b);if(a!=b) dj_fa[b]=a;
}
int vis[maxn],d[maxn],fa[maxn][20],minn[maxn][20];
void dfs(int u) {for(int p=head[u];p+1;p=e[p].next) {int v=e[p].v;if(d[v]!=-1) continue;d[v]=d[u]+1;fa[v][0]=u;minn[v][0]=e[p].w;dfs(v);}
}
int lca(int x,int y) {int i,j,mind=0x3f3f3f3f;if(d[x]<d[y]) swap(x,y);for(i=0;(1<<i)<=d[x];++i);--i;for(j=i;j>=0;--j) if(d[x]-(1<<j)>=d[y]) {mind=min(mind,minn[x][j]);x=fa[x][j];}if(x==y) return mind;for(j=i;j>=0;--j) if(fa[x][j]!=fa[y][j]) {mind=min(mind,min(minn[x][j],minn[y][j]));x=fa[x][j],y=fa[y][j];}mind=min(mind,min(minn[x][0],minn[y][0]));return mind;
}
int main() {scanf("%d%d",&n,&m);for(int i=1;i<=m;++i) scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);sort(E+1,E+m+1);for(int i=1;i<=n;++i) dj_fa[i]=i;memset(head,-1,sizeof(head));for(int i=1;i<=m;++i) {int u=E[i].u,v=E[i].v,w=E[i].w;if(dj_find(u)!=dj_find(v)) {dj_merge(u,v);insert(u,v,w);insert(v,u,w);vis[u]=vis[v]=1;}}int root;for(int i=1;i<=n;++i) if(dj_fa[i]==i&&vis[i]) root=i;memset(d,-1,sizeof(d));d[root]=0;dfs(root);for(int j=1;(1<<j)<=n;++j)for(int i=1;i<=n;++i) {fa[i][j]=fa[fa[i][j-1]][j-1];minn[i][j]=min(minn[i][j-1],minn[fa[i][j-1]][j-1]);}int q,a,b,first=1;scanf("%d",&q);for(int i=1;i<=q;++i) {scanf("%d%d",&a,&b);if(first) first=0;else putchar('\n');if(dj_find(a)!=dj_find(b)) printf("-1");else printf("%d",lca(a,b));}return 0;
}

AC代码

之所以代码里面那样做可以,是因为最大生成树所不包含的点仅仅是那些孤零零的点,而并查集本质就是一棵树(树的结点只有一个父亲,必须满足这个条件),这样并查集里父亲是自身的就是树根了(不唯一,不同的方法可以找到不同的树根)。两点之间无法到达就是指其中一个是孤零零的点。

转载于:https://www.cnblogs.com/Mr94Kevin/p/9650467.html

【计蒜客习题】蒜头君运送宝藏相关推荐

  1. 计蒜客:蒜头君吃桃(java)

    采用循环思想(递归调用) 递归是计算机编程中应用最广泛的一个技巧,也是比较难理解的一个技巧,所以我们打算花大量的时间来理解递归.所谓递归,就是函数调用函数自身 ,一个过程或者函数在其定义或说明中有直接 ...

  2. 【计蒜客】蒜头君上班 C++ and C语言

    蒜头君上班 蒜头君可以选择行走和骑车两种方式上班.但实际上,他并不清楚哪种方式更快,因为骑车总要找车.开锁.停车.锁车等,这要耽误一些时间. 假设找到自行车,开锁并骑上自行车的时间为 27 秒:停车锁 ...

  3. 【动态规划】计蒜客:蒜头君的日志(最长递增公共子序列)

    dp[i][j]:同时以nums[i]结尾和nums[j]结尾的最长递增公共子序列 初始化: dp[0][j]=0 dp[j][0]=0 状态转移方程: nums[i]!=nums[j] dp[i][ ...

  4. 【动态规划】计蒜客:蒜头君闯关(最长递增子序列的变体)

    题意: 求递增子序列之和的最大值 dp[i]:以nums[i]结尾的递增子序列之和的最大值  初始化:                 dp[0]=nums[0] 状态转移方程: dp[i]=max{ ...

  5. 【宽度优先搜索】计蒜客:蒜头君回家(带条件的BFS)

    8 10 P.####.#P# ..#..#...# ..#T##.#.# .......... ..##.##### .......... #####...## ###....S## 21 求最短步 ...

  6. 【计蒜客】蒜头君的旅游计划

    题目 思路 递归出口:如果你到达的点已经到达了所有城市. 最优性剪枝:如果你当前到达点的花费已经超过了当前的最优解,就直接退出. 代码 #include<bits/stdc++.h> us ...

  7. 计蒜客c语言 蒜头君招聘程序,计蒜客 数据结构 蒜头君筛选用户

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 测试了很多样例都是对的 但一直过不去 求大神( ⊙ o ⊙ )啊! #include #include using namespace std; clas ...

  8. 【计蒜客习题】消除字符串

    问题描述 蒜头君喜欢中心对称的字符串,即回文字符串.现在蒜头君手里有一个字符串 SS,蒜头君每次都会进行这样的操作:从 SS 中挑选一个回文的子序列,将其从字符串 SS 中去除,剩下的字符重组成新的字 ...

  9. 计蒜客习题:恋爱纪念日(C语言)

    蒜头君和花椰妹谈恋爱啦.祝福他们吧. 蒜头君想知道第他们的第 100100 天,200200 天 ... 纪念日.输入格式输入 44 个整数 y,m,d,ky,m,d,k,表示他们在一起的日期,保证是 ...

  10. 计蒜客 A1596.蒜头君王国 概率计算(dp)

    题目描述 原题链接 有一天,蒜头君当上了国王.蒜头君的王国有 n n n 坐城市,现在他需要在城市之间修建道路使得城市之间相互联通. 蒜头君是一个不会规划的人,他不知道哪些城市之间必须要有道路,所以对 ...

最新文章

  1. cs oracle语句跟踪,Oracle执行语句跟踪 使用sql trace实现语句追踪
  2. CVS 快速入门指南
  3. 初学Java你有这些疑惑吗?本文给你几个建议
  4. C和指针之函数之实现简单的printf函数(支持%d, %f, %c, %s)
  5. 无法渲染窗口发黄_基础c4d教程:OC渲染器的立体光照
  6. Linux Socket通信 C/S模型
  7. 深度好文:2018 年 NLP 应用和商业化调查报告
  8. redistemplate.opsforvalue 设置不过期_民法典即将实施!“离婚冷静期”倍受关注
  9. 105款移动应用程序就此被清理下架!
  10. 视频帧AI分析后编码
  11. GitHub 官方终于要出 App 了!手机上也能改Bug了...
  12. echarts3力引导布局,固定某节点
  13. 铁大自动选课工具使用说明
  14. 暗影精灵4如何调节风扇转速_关于解决暗影精灵4散热问题。
  15. 让传感器数据在三维地图上显示,更直观,更震撼!
  16. ODBC数据源无法添加EXCEL驱动,显示存在系统错误代码126:找不到指定模块
  17. android检测ibeacon电量,Android检测IBeacon热点的方法
  18. 微信小程序、公众号侵权投诉流程
  19. Android 国内阿里云镜像
  20. 9个面向前端开发者的有用VSCode 插件工具

热门文章

  1. 光流(一)--综述概览
  2. linux安装steam
  3. 雷丰阳spring系列的笔记_怒肝8个月源码,我成为了 Spring 开源贡献者
  4. “21天好习惯“第一期-1
  5. 【机器人操作系统】ROS话题编程
  6. SparkSession对象
  7. openresty入门 方法及指令
  8. bzoj4987: Tree(树形dp)
  9. 升级nodejs的方法(3)
  10. Oracle的数据并发与一致性详解(下)