题目传送门(内部题131)


输入格式

  第一行三个整数$n$、$m$和$Q$。
  接下来$m$行每行三个整数$x$、$y$、$z$($1\leqslant x,y\leqslant n,1\leqslant z\leqslant 1,000,000$),表示有一条连接$x$和$y$长度为$z$的边。
  接下来$Q$行每行两个整数$x$、$y$($x\neq y$),表示一组询问。


输出格式

  $Q$行每行一个整数,表示一组询问的答案。


样例

样例输入:

5 5 4
1 2 3
1 3 2
3 2 1
1 4 5
2 4 4
1 2
1 4
3 5
2 4

样例输出:

2
4
-1
4


数据范围与提示

  对于前$30\%$的测试数据,满足$1\leqslant n,m,Q\leqslant 1,000$。
  对于另外$30\%$的测试数据,保证图联通。
  对于$100\%$的测试数据,满足$1\leqslant n,m,Q\leqslant 300,000$。
  对于$100\%$的测试数据,保证不存在自环,但可能存在重边。
  请使用$scanf,printf$或速度更快的读入输出方式。


题解

有人问我$30\%$的暴力怎么打(问题是$ta$还$A$了)……

那我就简单说一下。

最短路思想,用$Dijkstra$,将原本的$dis[v]=dis[u]+e[i].w$改成$dis[v]=\max(dis[u],e[i].w)$就好了。

千万不要想当然,比方说下面这份代码$\downarrow$

认真看一下,虽说时间复杂度是对的,但是如果如下面这张图$\downarrow$

我们可能会选择$x\stackrel{2}{\rightarrow}o\stackrel{1}{\rightarrow}y$这条路径;然而当发现$x\stackrel{1}{\rightarrow}o$更优时会发现$o\rightarrow y$已经走过了,就不会再更新答案,这也就是为什么最短路不是这么求。

现在来说正解吧,先来考虑联通的情况。

这个最优路径上的所有边一定位于最小生成树上,所以可以求$x,y$到$lca$上的最长边即可。

不联通的情况也无非就是记录一下两个点在不在一个联通块内即可。

时间复杂度:$\Theta(m\log m+q\log n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct node{int x,y,z;bool d;}b[300001];
struct rec{int nxt,to,w;}e[600001];
int head[300001],cnt,tot;
int n,m,Q;
int f[300001],depth[300001],bel[300001],fa[300001][21],mi[300001][21];
bool cmp(node a,node b){return a.z<b.z;}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void add(int x,int y,int w)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
e[cnt].w=w;
head[x]=cnt;
}
void dfs(int x)
{
bel[x]=tot;
for(int i=head[x];i;i=e[i].nxt)
{
if(depth[e[i].to])continue;
depth[e[i].to]=depth[x]+1;
fa[e[i].to][0]=x;
mi[e[i].to][0]=e[i].w;
for(int j=1;j<=20;j++)
{
fa[e[i].to][j]=fa[fa[e[i].to][j-1]][j-1];
mi[e[i].to][j]=max(mi[e[i].to][j-1],mi[fa[e[i].to][j-1]][j-1]);
}
dfs(e[i].to);
}
}
int LCA(int x,int y)
{
if(depth[x]>depth[y])swap(x,y);
int res=0;
for(int i=20;i>=0;i--)
if(depth[fa[y][i]]>=depth[x])
{
res=max(res,mi[y][i]);
y=fa[y][i];
}
if(x==y)return res;
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
res=max(res,max(mi[x][i],mi[y][i]));
x=fa[x][i];y=fa[y][i];
}
return max(res,max(mi[x][0],mi[y][0]));
}
int main()
{
scanf("%d%d%d",&n,&m,&Q);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++)scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z);
sort(b+1,b+m+1,cmp);
for(int i=1;i<=m;i++)
{
int x=find(b[i].x);
int y=find(b[i].y);
if(x==y)continue;
b[i].d=1;
f[y]=x;
}
for(int i=1;i<=m;i++)
if(b[i].d)
{
add(b[i].x,b[i].y,b[i].z);
add(b[i].y,b[i].x,b[i].z);
}
for(int i=1;i<=n;i++)
if(!depth[i])
{
tot++;
depth[i]=1;
dfs(i);
}
while(Q--)
{
int x,y;
scanf("%d%d",&x,&y);
if(bel[x]!=bel[y])puts("-1");
else printf("%d\n",LCA(x,y));
}
return 0;
}

rp++

最新文章

  1. iOS UIView动画效果 学习笔记
  2. Fiddler使用AutoResponder进行本地文件和线上文件的映射
  3. WinForm 快捷键设置
  4. JavaScript对象属性 constructor
  5. maven项目导出依赖的Jar包以及项目本身以jar包形式导出详细教程
  6. 《团队作业》五小福团队--UNO的博客链接汇总
  7. URL中可以出现的字符
  8. win7下配置Tomcat
  9. python-跨域问题
  10. 为什么要用GCD-Swift2.x
  11. java环境配置针对win10(电脑重装必备) 最后一步很重要
  12. Zookeeper 快速理解
  13. [LeetCode] 176. Second Highest Salary_Easy tag: SQL
  14. event bManualResult
  15. 如何修改ionic中android程序的包名
  16. 铁乐学python_Day42_锁和队列
  17. 源码包安装 NGINX时候遇到的错误以及解决办法!
  18. 强大的CSS 属性选择符 配合 stylish 屏蔽新浪微博信息流广告
  19. 大数据(8) - hive的安装与使用
  20. Hyper:基于Hypervisor的容器化解决方案

热门文章

  1. python 操作mongodb 文件相关
  2. python_0基础开始_day09
  3. 11 Scrapy框架之递归解析和post请求
  4. 黑客正在使用美国NSA泄露的工具进行挖矿
  5. maven学习之路三
  6. trigger添加及表达式
  7. 【2019.3.20】NOI模拟赛
  8. glViewport函数用法
  9. spring注解 @profile 以及 注解@Slf4j
  10. 支付宝支付之扫码支付(电脑网站支付)、H5支付(手机网站支付)相关业务流程分析总结