• 洛谷1967货车运输


    题目:https://www.luogu.org/problemnew/show/P1967

    倍增LCA裸题。用了在线。还有离线O(n)做法、树链剖分做法,暂不管了。

    (自己程序的)坑点:1.xnt从1开始!2.数组大小!!!

    重边在最大生成树的时候就解决啦~

      不然我就要进了子节点的dfs以后遍历一遍它的边,从与fa相连者中找出最大的作为mn[ ][0]的值;用vis标记使fa再走到自己时不进dfs了。

    值得注意的地方是它可能是一个森林。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+5,M=5e5+5,lm=17;const ll INF=0x7fffffff;
    int n,m,head[N],xnt=1,dep[N],pre[N][lm+5],q;
    ll mn[N][lm+5],fa[N];
    bool use[M<<1],in[N];
    struct Edge{
        int next,from,to,bh;ll w;
        Edge(int n=0,int f=0,int t=0,int b=0,ll w=0):next(n),from(f),to(t),bh(b),w(w) {}
    }edge[M<<1],tp[N<<1];
    bool cmp(Edge a,Edge b){return a.w>b.w;}
    int find(int a)
    {
        if(fa[a]==a)return a;
        return fa[a]=find(fa[a]);
    }
    void kruskal()
    {
        memcpy(tp,edge,sizeof tp);
        sort(tp+1,tp+xnt+1,cmp);
        for(int i=1,u,v,k;i<=xnt;i++)
            if(find(u=tp[i].from)!=find(v=tp[i].to))
                fa[find(u)]=find(v),use[k=tp[i].bh]=use[k^1]=1;
    }
    void dfs(int cur,int fa)
    {
        pre[cur][0]=fa;dep[cur]=dep[fa]+1;
        for(int i=1;i<=lm;i++)
        {
            int k=pre[cur][i-1];//不是i>>1 
            if(!pre[k][i-1])break;
            pre[cur][i]=pre[k][i-1];
            mn[cur][i]=min(mn[cur][i-1],mn[k][i-1]);//不用赋初值了 
        }
        for(int i=head[cur],v;i;i=edge[i].next)
            if(use[i]&&(v=edge[i].to)!=fa)mn[v][0]=edge[i].w,dfs(v,cur);
    }
    ll lca(int x,int y)
    {
        ll ans=INF;
        if(dep[x]<dep[y])swap(x,y);
        int d=dep[x]-dep[y];
        for(int i=lm;i>=0;i--)//
            if(d&(1<<i)){ans=min(ans,mn[x][i]);x=pre[x][i];}
        if(x==y)return ans;//
        for(int i=lm;i>=0;i--)
            if(pre[x][i]!=pre[y][i])
            {ans=min(ans,min(mn[x][i],mn[y][i]));x=pre[x][i];y=pre[y][i];}
        return min(ans,min(mn[x][0],mn[y][0]));
    }
    int main()
    {
        scanf("%d%d",&n,&m);int x,y;ll z;
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%lld",&x,&y,&z);
            edge[++xnt]=Edge(head[x],x,y,xnt,z);head[x]=xnt;
            edge[++xnt]=Edge(head[y],y,x,xnt,z);head[y]=xnt;
        }
        kruskal();
        for(int i=1;i<=n;i++)
            if(fa[i]==i)dfs(i,0);//森林 
    //    for(int j=1;j<=lm;j++)
    //        for(int i=1;i<=n;i++)
    //            {
    //                mn[i][j]=min(mn[pre[i][j-1]][j-1],mn[i][j-1]);
    //                pre[i][j]=pre[pre[i][j-1]][j-1];
    //            }
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&x,&y);
            if(find(x)!=find(y))printf("-1
    ");
            else printf("%lld
    ",lca(x,y));
        }
    }
  • 相关阅读:
    Modbus Tcp[转载]
    NModbus使用示例
    “SAP.Middleware.Connector.RfcConfigParameters”的类型初始值设定项引发异常,解决方法
    .net x64 x86 any cpu
    虚拟机vmware 15的安装和使用
    nuget下载包,搜索到的包很少
    做一款简单、高效、好用的文件同步工具
    [WeUiSharp] 基于WPF实现的仿Windows桌面版微信UI界面库
    C语言----结构与联合(基础篇十一)
    C语言----字符串(基础篇十)
  • 原文地址:https://www.cnblogs.com/Narh/p/8886782.html
Copyright © 2020-2023  润新知