博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
倍增加强学习笔记
阅读量:5108 次
发布时间:2019-06-13

本文共 2590 字,大约阅读时间需要 8 分钟。

加强?不可能的!

因为这几次考试中的倍增孤都挂了,而且发现自己倍增打得比较少,所以用一篇随笔来再学习。

直接开题:

题意:给定一张图,每条边上有限重,有Q个询问,每个询问求x到y的最大运输重量。

开局思路暴力?一看范围……

算了吧,要是孤还想活着就别这么打……

我们再看一下,也就是说x到y中间有很多道路,我们要求出这些道路最小值的最大值。

不妨先考虑如何保证最大,我们可以从中选出一些边,保证联通的情况下有最小值的最大值

诶,好像就是要构一棵最大生成树,再跑LCA就可以啦(毕竟暴跳就会TLE啊)

上代码:

#include
using namespace std;inline int read(){ int f=1,w=0;char x=0; while(x<'0'||x>'9') {
if(x=='-') f=-1; x=getchar();} while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();} return w*f;}int n,m,num_edge,fa[200001][21],w[200001][21],q;struct Edge{
int u,v,w;} line[200001];int head[50001],f[200001],vis[200001],dep[200001];struct Tree{
int next,to,dis;} edge[200001];inline bool cmp(Edge a,Edge b) {
return a.w>b.w;}inline int find(int x) {
return f[x]==x?x:f[x]=find(f[x]);}inline void add(int from,int to,int dis){ edge[++num_edge].next=head[from]; edge[num_edge].to=to; edge[num_edge].dis=dis; head[from]=num_edge;}void dfs(int pos){ vis[pos]=1; for(int i=head[pos];i;i=edge[i].next) if(!vis[edge[i].to]) { dep[edge[i].to]=dep[pos]+1; fa[edge[i].to][0]=pos; w[edge[i].to][0]=edge[i].dis; dfs(edge[i].to); }}inline int LCA(int x,int y){ if(find(x)!=find(y)) return -1; if(dep[x]>dep[y]) swap(x,y); int ans=999999999; for(int i=20;i>=0;i--) if(dep[fa[y][i]]>=dep[x]) { ans=min(ans,w[y][i]); y=fa[y][i]; } if(x==y) return ans; for(int i=20;i>=0;i--) if(fa[x][i]!=fa[y][i]) { ans=min(ans,min(w[x][i],w[y][i])); y=fa[y][i]; x=fa[x][i]; } ans=min(ans,min(w[x][0],w[y][0])); return ans;}int main(){ n=read(); m=read(); for(int i=1;i<=m;i++) line[i].u=read(),line[i].v=read(),line[i].w=read(); sort(line+1,line+m+1,cmp); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { int u=find(line[i].u); int v=find(line[i].v); if(u!=v) f[u]=v,add(line[i].u,line[i].v,line[i].w),add(line[i].v,line[i].u,line[i].w); } for(int i=1;i<=n;i++) if(!vis[i]) { dep[i]=1; dfs(i); fa[i][0]=i; w[i][0]=999999999; } for(int j=1;j<=20;j++) for(int i=1;i<=n;i++) { fa[i][j]=fa[fa[i][j-1]][j-1]; w[i][j]=min(w[i][j-1],w[fa[i][j-1]][j-1]); } q=read(); for(int i=1;i<=q;i++) { int x=read(),y=read(); printf("%d\n",LCA(x,y)); }}

 

转载于:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/10387859.html

你可能感兴趣的文章
5.9UDP客户端服务器-基于OK6410
查看>>
java自学基础、项目实战网站推荐
查看>>
软件包的使用
查看>>
linux中启动与终止lnmp的脚本
查看>>
gdb中信号的处理[转]
查看>>
学习Javascript闭包(Closure)
查看>>
LeetCode【709. 转换成小写字母】
查看>>
如何在Access2007中使用日期类型查询数据
查看>>
Jzoj4757 树上摩托
查看>>
CF992E Nastya and King-Shamans(线段树二分+思维)
查看>>
基于docker的spark-hadoop分布式集群之一: 环境搭建
查看>>
oracle 几个时间函数探究
查看>>
第一个Java Web程序
查看>>
Atomic
查看>>
div 显示滚动条与div显示隐藏的CSS代码
查看>>
Redis-1-安装
查看>>
Access denied for user ''@'localhost' to database 'mysql'
查看>>
部署支持 https 的 Nginx 服务
查看>>
‘Cordova/CDVPlugin.h’ file not found
查看>>
WebAssembly是什么?
查看>>