博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并
阅读量:6279 次
发布时间:2019-06-22

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

思路:

Kruskal求最大生成树+倍增LCA

// by SiriusRen#include 
#include
#include
using namespace std;#define N 105000int n,m,tot=0,xx,yy,zz,ans;int first[N],v[N*10],next[N*10],w[N*10],f[N],dep[N],fa[N][20],minn[N][20];int find(int x){return x==f[x]?x:f[x]=find(f[x]);}struct EDGE{int from,to,weight;}Edge[50500];void add(int x,int y,int z){ w[tot]=z,v[tot]=y; next[tot]=first[x]; first[x]=tot++;}bool cmp(EDGE x,EDGE y){return x.weight>y.weight;}void dfs(int x){ for(int j=1;j<=18;j++){
fa[x][j]=fa[fa[x][j-1]][j-1]; minn[x][j]=min(minn[x][j-1],minn[fa[x][j-1]][j-1]); } for(int i=first[x];~i;i=next[i]) if(dep[v[i]]==-1){
dep[v[i]]=dep[x]+1; fa[v[i]][0]=x;minn[v[i]][0]=w[i]; dfs(v[i]); }}int lca(int x,int y){ int ans=0x3fffffff; if(dep[x]
=0;i--)if(dep[x]>=dep[y]+(1<
=0;i--) if(fa[x][i]!=fa[y][i]){
ans=min(ans,min(minn[x][i],minn[y][i])); x=fa[x][i];y=fa[y][i]; } return min(ans,min(minn[x][0],minn[y][0]));}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)f[i]=i; memset(dep,-1,sizeof(dep)); memset(minn,0x3f,sizeof(minn)); memset(first,-1,sizeof(first)); for(int i=1;i<=m;i++){
scanf("%d%d%d",&xx,&yy,&zz); Edge[i].from=xx;Edge[i].to=yy;Edge[i].weight=zz; } sort(Edge+1,Edge+1+m,cmp); for(int i=1;i<=m;i++) if(find(Edge[i].from)!=find(Edge[i].to)){
f[find(Edge[i].from)]=find(Edge[i].to); add(Edge[i].from,Edge[i].to,Edge[i].weight); add(Edge[i].to,Edge[i].from,Edge[i].weight); } dep[find(1)]=0;dfs(find(1)); scanf("%d",&m); while(m--){
scanf("%d%d",&xx,&yy); if(~dep[xx]&&~dep[yy])printf("%d\n",lca(xx,yy)); else puts("-1"); }}

这里写图片描述

队长讲了还有一中很奇怪的方法可以乱搞。

就是:Bling 并查集!
我们可以想到Kruskal进行的过程中是把两个连通块连起来,中间连的边一定比连通块里面的边要小。
那么我们可以考虑按秩合并。。可以证明这样树的高度是log的。
然后直接暴力求LCA即可
网上是这么说的:

启发式并查集,就是维护每个集合的深度,在合并两个集合的时候把小的那个集合挂在大集合下。

在此题中呢,求最大生成树的同时,不把新加入的一条边作为计算答案的树,而是把两个集合的祖先加入树中,边权就是原来边的两个边权。看到这,不禁产生了疑问,树的边权和形态与求出的最大生成树都不一样,为啥能做???其实没有关系,因为新加入的边不影响
原来集合中两点的答案,合并的两个集合中的点合并后肯定要经过原来这条边,那我把祖先接起来用原来边的边权也是一样的。
但是这么做,由于使用了启发式合并,那么最后新的树高度可以证明不会超过logn(其实我也不会证大笑),那么我们不用倍增处理这棵树,直接暴力求lca即可,不仅代码短,而且常数小!!!

// by SiriusRen#include 
#include
#include
using namespace std;#define N 105000int n,m,tot=0,xx,yy,zz;int first[N],v[N*10],next[N*10],w[N*10],f[N],dep[N],fa[N],size[N],minn[N];int find(int x){
return x==f[x]?x:f[x]=find(f[x]);}struct EDGE{
int from,to,weight;}Edge[50500];void add(int x,int y,int z){w[tot]=z,v[tot]=y;next[tot]=first[x];first[x]=tot++;}bool cmp(EDGE x,EDGE y){
return x.weight>y.weight;}void dfs(int x){ for(int i=first[x];~i;i=next[i]) if(dep[v[i]]==-1){ dep[v[i]]=dep[x]+1; fa[v[i]]=x;minn[v[i]]=w[i]; dfs(v[i]); }}void lca(int x,int y){ int ans=0x3fffffff; if(dep[x]>dep[y])swap(x,y); while(dep[x]!=dep[y])ans=min(minn[y],ans),y=fa[y]; while(x!=y){ ans=min(ans,min(minn[x],minn[y])); x=fa[x];y=fa[y]; } printf("%d\n",ans); return;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)size[i]=1; for(int i=1;i<=n;i++)f[i]=i; memset(dep,-1,sizeof(dep)); memset(first,-1,sizeof(first)); memset(minn,0x3f,sizeof(minn)); for(int i=1;i<=m;i++){ scanf("%d%d%d",&xx,&yy,&zz); Edge[i].from=xx;Edge[i].to=yy;Edge[i].weight=zz; } sort(Edge+1,Edge+1+m,cmp); for(int i=1;i<=m;i++){ int fx=find(Edge[i].from),fy=find(Edge[i].to); if(fx!=fy){ if(size[fx]>size[fy])swap(fx,fy); f[fx]=fy;size[fy]+=fx; add(fx,fy,Edge[i].weight);add(fy,fx,Edge[i].weight); } } dep[find(1)]=0;dfs(find(1)); scanf("%d",&m); while(m--){ scanf("%d%d",&xx,&yy); if(~dep[xx]&&~dep[yy])lca(xx,yy); else puts("-1"); }}

转载于:https://www.cnblogs.com/SiriusRen/p/6532409.html

你可能感兴趣的文章
Python sin() 函数
查看>>
Python isalnum() 方法
查看>>
Nginx负载均衡器处理Session共享的几种方法(转)
查看>>
转 MySQL问题排查工具介绍
查看>>
Linux、apache 无法使用PHP创建目录和文件
查看>>
hi模板文件报乱码问题
查看>>
Java 远程通讯技术及原理分析
查看>>
ORM框架之------Dapper,Net下无敌的ORM
查看>>
R语言绘图时的边界碰撞问题
查看>>
深度可分离卷积结构(depthwise separable convolution)计算复杂度分析
查看>>
IntelliJ IDEA 常用设置讲解
查看>>
软件的描述x
查看>>
深度 | AI芯片之智能边缘计算的崛起——实时语言翻译、图像识别、AI视频监控、无人车这些都需要终端具有较强的计算能力,从而AI芯片发展起来是必然,同时5G网络也是必然...
查看>>
spring boot微服务改造冲突
查看>>
OAuth2 Demo PHP
查看>>
真机测试出现INSTALL_FAILED_USER_RESTRICTED安装错误
查看>>
Mybateis mapper 接口 example 用法
查看>>
js图片转base64并压缩
查看>>
关于server和虚拟主机的差别
查看>>
散列表(二)冲突处理的方法之链地址法的实现: 哈希查找
查看>>