zoukankan      html  css  js  c++  java
  • Luogu P1967 货车运输 倍增+最大生成树

    看见某大佬在做,决定补一发题解$qwq$


    首先跑出最大生成树(注意有可能不连通),然后我们要求的就是树上两点间路径上的最小边权。 我们用倍增的思路跑出来$w[u][j]$,表示$u$与的它$2^j$的祖先路径上的最小边权(其实是为了配合$lca$),然后求$lca$时顺便记一下最小边权。

    码风清奇别在意是之前写的

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define R register int 
    using namespace std;
    namespace jack {
        #define N 100010
        #define M 500010
        #define Inf 0x3f3f3f3f
        int n,m,q,cnt,lim,fir[N],dep[N],f[N][20],w[N][20],fa[N];
        bool vis[N];
        struct Edge {
            int u,v,w;
            bool operator < (const Edge& y)const{return w>y.w;}
        }E[M];
        struct edge {int v,w,nxt;}e[M];
        inline int g() {
            R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
            do ret=(ret<<3)+(ret<<1)+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
        }
        //inline int min(int a,int b) {return a<b?a:b;}
        inline void add(int u,int v,int w) {e[++cnt].v=v,e[cnt].w=w,e[cnt].nxt=fir[u],fir[u]=cnt;}
        int getf(int x) {return x==fa[x]?x:fa[x]=getf(fa[x]);}
        inline bool merge(int u,int v) {
            R uf=getf(u),vf=getf(v);
            if(uf==vf) return true;
            fa[uf]=vf; return false;
        }
        inline void kruskal() {
            sort(E+1,E+m+1);
            for(R i=1;i<=n;i++) fa[i]=i;
            for(R i=1,u=E[i].u,v=E[i].v,w=E[i].w;i<=m;i++,u=E[i].u,v=E[i].v,w=E[i].w) 
                if(!merge(u,v)) {add(u,v,w),add(v,u,w);}
        }
        void dfs(int u) {
            vis[u]=true;
            for(R i=fir[u];i;i=e[i].nxt) {
                R v=e[i].v; if(dep[v]) continue;
                dep[v]=dep[u]+1;f[v][0]=u,w[v][0]=e[i].w;
                for(R j=1,fa=u;f[fa][j];j++) f[v][j+1]=f[fa][j],fa=f[fa][j];
                dfs(v);
            }
        }
        inline int lca(int u,int v) {
            if(getf(u)!=getf(v)) return -1; R ans=Inf;
            if(dep[u]<dep[v]) swap(u,v);
            for(R i=lim;i>=0;i--) if(dep[f[u][i]]>=dep[v]) ans=min(ans,w[u][i]),u=f[u][i];
            if(u==v) return ans;
            for(R i=lim;i>=0;i--) if(f[u][i]!=f[v][i]) ans=min(ans,min(w[u][i],w[v][i])),u=f[u][i],v=f[v][i];
            return min(ans,min(w[u][0],w[v][0]));
        }
        void main() {
            n=g(),m=g(); lim=log2(n)+1;
            for(R i=1;i<=m;i++) {E[i].u=g(),E[i].v=g(),E[i].w=g();}
            kruskal();
            for(R i=1;i<=n;i++) if(!vis[i]) {dep[i]=1;dfs(i);f[i][0]=i,w[i][0]=Inf;}
            for(R i=1;i<=lim;i++) for(R j=1;j<=n;j++) {
                f[j][i]=f[f[j][i-1]][i-1]; 
                w[j][i]=min(w[j][i-1],w[f[j][i-1]][i-1]);
            } q=g();
            for(int i=1; i<=q; i++) {R u=g(),v=g(); printf("%d
    ",lca(u,v));}
        }
    }
    
    signed main() {jack::main();}
  • 相关阅读:
    开发趋势
    常用的meta
    meta基础
    HTTP请求方法GET和POST
    same-origin policy----wikipedia
    跨域——同源策略(译)
    DNS问答
    TCP/IP的整理
    鉴权方法
    Web攻击技术---OWASP top
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11000272.html
Copyright © 2011-2022 走看看