LOJ137(LOJ6021)

这篇博客介绍了如何利用最小生成树和最近公共祖先(LCA)解决LOJ137问题。文章指出两点间最小瓶颈路径在最小生成树上,从而将问题转化为寻找树上两点间路径的最大边。通过Kruskal算法建立图,并使用DFS序结合RMQ(ST表)优化查询,最终达到O(N*logN+E*logM+Q)的复杂度。
摘要由CSDN通过智能技术生成

LOJ137

这题,真心整死人。。
首先,国家集训队论文里有一篇有关文章:

郭华阳 《RMQ与LCA问题》

然后有一个定理:

两点间最小瓶颈路一定是最小生成树上两点间唯一路径上的最大边

所以先求原图的最小生成树,这题就变成求树上两点间唯一路径上的最大边了
然后倍增? O(10000000log) O ( 10000000 ∗ l o g ) ?T到飞起。。再怎么卡常,LOJ跑得再快,依然为 O() O ( 不 能 过 )

#pragma GCC optimize(6)
#include<cstdio>
#include<algorithm>
#define rnd() (A=(A*B+C)%P)
#define __R register
#define IN inline
using namespace std;
const int maxn=(7e4)+5,maxE=(1e5)+5,Log=20,TT=1000000007;
template<typename Tp>IN Tp Max(Tp x,Tp y){
  return x>y?x:y;}
int Ans,n,m,Q,A,B,C,P,fa[maxn],cnt[maxn];
struct ff{
    int x,y,w;
    IN bool operator <(const ff b)const{
  return w<b.w;}
}E[maxE];
IN int getfa(int x){
  return fa[x]==x?x:fa[x]=getfa(fa[x]);}

int tot,lnk[maxn],nxt[maxn<<1],son[maxn<<1],w[maxn<<1],dep[maxn],up[maxn][Log],val[maxn][Log],pow[Log],D[maxn];
IN void add_e(int x,int y,int z){son[++tot]=y,w[tot]=z,nxt[tot]=lnk[x],lnk[x]=tot;}
IN void DFS(int x,int dad){
    dep[x]=dep[dad]+1;
    for(__R int i=1;pow[i]<=dep[x];i++) up[x][i]=up[up[x][i-1]][i-1],val[x][i]=Max(val[x][i-1],val[up[x][i-1]][i-1]);
    for(__R int j=lnk[x];j;j=nxt[j])if(son[j]!=dad){
        up[son[j]][0]=x,val[son[j]][0]=w[j];
        DFS(son[j],x);
    }
}
IN int LCA(int x,int y){
    int ans=0;
    if(dep[x]<dep[y]){
  int t=x;x=y,y=t;}
    while(dep[x]>dep[y]){
  if(ans<val[x][D[dep[x]-dep[y]]-1]) ans=val[x][D[dep[x]-dep[y]]-1];x=up[x][D[dep[x]-dep[y]]-1];}
    if(x==y) return ans;
    for(__R int k=D[dep[x]-1]-1;k>=0;k--) if(up[x][k]!=up[y][k]){
  if(ans<val[x][k]) ans=val[x][k];if(ans<val[y][k]) ans=val[y][k];x=up[x][k],y=up[y][k];}
    if(ans<val[x][0]) ans=val[x][0];if(ans<val[y][0]) ans=val[y][0];
    return ans;
}

IN char gt(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值