Luogu P1967 货车运输

Luogu P1967 货车运输

十分经典的LCA题目。最大生成树+倍增LCA

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read(){
    int k=0; char c=getchar();
    for(;c<'0'||c>'9';) c=getchar();
    for(;c>='0'&&c<='9';c=getchar())
      k=(k<<3)+(k<<1)+c-48;
    return k;
}
struct zzz{
    int f,t,len;
}mst[50010]; int fa[10010];
struct hhh{
    int t,len,nex;
}lca[10010<<1]; int head[10010],tot;
void add(int x,int y,int z){
    lca[++tot].t=y;
    lca[tot].len=z;
    lca[tot].nex=head[x];
    head[x]=tot;
}
int findd(int x){
    return x==fa[x]? x: fa[x]=findd(fa[x]);
}
bool cmp(zzz x,zzz y){
    return x.len>y.len;
}
int f[10010][32],deth[10010],lg[10010],maxx[10010][32];
bool vis[10010];
void dfs(int from,int fath){
    vis[from]=1;
    f[from][0]=fath; deth[from]=deth[fath]+1;
    for(int i=1;1<<i<=deth[from];i++){
        f[from][i]=f[f[from][i-1]][i-1];
        maxx[from][i]=min(maxx[f[from][i-1]][i-1],maxx[from][i-1]);
    }
    for(int i=head[from];i;i=lca[i].nex)
        if(lca[i].t!=f[from][0]){
            maxx[lca[i].t][0]=lca[i].len;
            dfs(lca[i].t,from); 
        }
}
int LCA(int x,int y){
    int ans=0x7fffffff;
    if(deth[x]<deth[y]) swap(x,y);
    while(deth[y]<deth[x]){
        ans=min(ans,maxx[x][lg[deth[x]-deth[y]]-1]);
        x=f[x][lg[deth[x]-deth[y]]-1];
    }
    if(x==y) return ans;
    for(int i=lg[deth[x]];i>=0;i--)
      if(f[x][i]!=f[y][i]){
          ans=min(ans,min(maxx[x][i],maxx[y][i]));
          x=f[x][i],y=f[y][i];
      }
    return min(ans,min(maxx[x][0],maxx[y][0]));
}
int main(){
    memset(maxx,127,sizeof(maxx));
    int n=read(),m=read();
    for(int i=1;i<=n;i++)
      fa[i]=i;
    for(int i=1;i<=m;i++)
      mst[i].f=read(),mst[i].t=read(),mst[i].len=read();
    sort(mst+1,mst+m+1,cmp);
    int tot=0;
    for(int i=1;i<=m;i++){
        int x=findd(mst[i].f),y=findd(mst[i].t);
        if(x!=y){
            fa[x]=y;
            add(mst[i].f,mst[i].t,mst[i].len);
            add(mst[i].t,mst[i].f,mst[i].len);
            tot++;
        }
        if(tot==n-1) break;
    }
    for(int i=1;i<=n;i++)
      lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    for(int i=1;i<=n;i++){
        if(!vis[i])
          dfs(i,0);
    }
    int q=read();
    for(int i=1;i<=q;i++){
        int x=read(),y=read();
        if(findd(x)!=findd(y)){
            printf("-1\n"); continue;
        }
        else printf("%d\n",LCA(x,y));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wxl-Ezio/p/9294471.html