zoukankan      html  css  js  c++  java
  • bzoj1977 [BeiJing2010组队]次小生成树 Tree——严格次小生成树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1977

    因为严格,所以要记录到 LCA 的一个次小值;

    很快写好,然后改掉一堆错误后终于过了样例!然而交上去1WA;

    又改了半天,还是WA,于是放弃,抄题解好久...

    然而就在我调了一个小时终于锁定错误就在那个子函数里的时候才突然看到了自己的明显惊天大错误是怎么回事??!!!稍微改了一下下就完美AC。。。

    不过还有点收获,把求各种层次的 f 放在 dfs 函数里会比单独拿出来再求一遍快 1000+ms 哦~

    题解的写法是直接看 u 到 lca 和 v 到 lca 路上的值,而我是求 lca 的过程中求值的,还是喜欢我的写法;

    题解的写法放在注释里了;

    囧。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const maxn=1e5+5,maxm=3e5+5,inf=1e9;
    int n,m,f[maxn][22],dep[maxn],mx[maxn][22],nmx[maxn][22];//22
    int hd[maxn],ct,fa[maxn],d[maxn],mnn;
    ll ans;//ll
    bool vis[maxn],used[maxm];
    struct P{int u,v,w;}e[maxm];
    struct T{
        int mx,nmx;
        T(int x=0,int n=0):mx(x),nmx(n) {}
    };
    struct N{
        int to,nxt,w;
        N(int t=0,int n=0,int w=0):to(t),nxt(n),w(w) {}
    }ed[maxn<<1];
    bool cmp(P x,P y){return x.w<y.w;}
    void add(int x,int y,int w){ed[++ct]=N(y,hd[x],w); hd[x]=ct;}
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void dfs(int x)
    {
        for (int i=1; i<=20; i++)//写在这里较快 
            {
                if(dep[x]<(1<<i))break;
                f[x][i]=f[f[x][i-1]][i-1];
                mx[x][i]=max(mx[x][i-1],mx[f[x][i-1]][i-1]);
                if (mx[x][i-1]==mx[f[x][i-1]][i-1])
                    nmx[x][i]=max(nmx[x][i-1],nmx[f[x][i-1]][i-1]);
                else
                    nmx[x][i]=min(mx[x][i-1],mx[f[x][i-1]][i-1]),
                    nmx[x][i]=max(nmx[x][i],nmx[x][i-1]),
                    nmx[x][i]=max(nmx[x][i],nmx[f[x][i-1]][i-1]);
            }
        vis[x]=1;
        for(int i=hd[x],u;i;i=ed[i].nxt)
            if(!vis[u=ed[i].to])
            {
                f[u][0]=x; dep[u]=dep[x]+1;
                mx[u][0]=ed[i].w;
    //            nmx[u][0]=ed[i].w;//无! 
                d[u]=ed[i].w;
                dfs(u);
            }
    }
    void init()
    {
        dep[1]=1; dfs(1);
    //    for(int j=1;j<=20;j++)
    //        for(int i=1;i<=n;i++)
    //        {
    //            int tmx=mx[f[i][j-1]][j-1],tnx=nmx[f[i][j-1]][j-1];
    //            f[i][j]=f[f[i][j-1]][j-1];
    //            mx[i][j]=max(mx[i][j-1],tmx);
    //            if(tmx>mx[i][j-1]) nmx[i][j]=max(mx[i][j-1],tnx);
    //            else if(tmx==mx[i][j-1]) nmx[i][j]=max(nmx[i][j-1],tnx);
    //            else nmx[i][j]=max(nmx[i][j-1],tmx);
    //        }
    }
    void ch(int &rmx,int &rnx,int tmx,int tnx)
    {
        if(tmx>rmx)
        {
            rnx=max(tnx,rmx);
            rmx=tmx;
        }
        else if(tmx==rmx) rnx=max(tnx,rnx);
        else rnx=max(rnx,tmx);
    }
    T lca(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);
        int k=dep[x]-dep[y],rmx=-1,rnx=-1;
        for(int i=20;i>=0;i--)
    //        if((1<<i)&k){rmx=mx[x][i]; rnx=nmx[x][i]; x=f[x][i];}//x放在后面修改! 
            if((1<<i)&k){ch(rmx,rnx,mx[x][i],nmx[x][i]); x=f[x][i];}//!!!!!!囧 
        for(int i=20;i>=0;i--)
            if(f[x][i]!=f[y][i])
            {
                ch(rmx,rnx,mx[x][i],nmx[x][i]);
                ch(rmx,rnx,mx[y][i],nmx[y][i]);
                x=f[x][i]; y=f[y][i]; //后面改!! 
            }
        if(x!=y) ch(rmx,rnx,max(d[x],d[y]),min(d[x],d[y]));
        return T(rmx,rnx);
    }
    //int LCA(int x,int y)
    //{
    //    if(dep[x]<dep[y])swap(x,y);
    //    int k=dep[x]-dep[y];
    //    for(int i=20;i>=0;i--)
    //        if((1<<i)&k){rmx=mx[x][i]; rnx=nmx[x][i]; x=f[x][i];} 
    //    for(int i=20;i>=0;i--)
    //        if(f[x][i]!=f[y][i])
    //        {
    //            x=f[x][i]; y=f[y][i];
    //        }
    //    if(x==y)return x;
    //    return f[x][0];
    //}
    //T work(int x,int lca)
    //{
    //    T ret;
    //    int maxx1=-1,maxx2=-1;
    //    int d=dep[x]-dep[lca];
    //    for (int i=0; i<=20; i++)
    //        if (d&(1<<i))
    //            {
    //                ch(maxx1,maxx2,mx[x][i],nmx[x][i]);
    //                x=f[x][i];
    //            }
    //    ret.mx=maxx1,ret.nmx=maxx2;
    //    return ret;
    //}
    //T solve(int x)
    //{
    //    T ret;
    //    int u=e[x].u,v=e[x].v,lca=LCA(u,v);
    //    T uu=work(u,lca);
    //    T vv=work(v,lca);
    //    ret.mx=max(uu.mx,vv.mx);
    //    if(uu.mx>vv.mx) ret.nmx=max(vv.mx,uu.nmx);
    //    else if(uu.mx==vv.mx) ret.nmx=max(vv.nmx,uu.nmx);
    //    else ret.nmx=max(uu.mx,vv.nmx);
    //    return ret;
    //}
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=n;i++)fa[i]=i;
        int cnt=0;
        for(int i=1,u,v;i<=m;i++)
            if(find(u=e[i].u)!=find(v=e[i].v))
            {
                cnt++;
                fa[find(u)]=find(v);
                used[i]=1; ans+=e[i].w;
                add(u,v,e[i].w); add(v,u,e[i].w);
                if(cnt==n-1)break;
            }
        init(); 
        mnn=inf;
        for(int i=1;i<=m;i++)
        {
            if(used[i])continue;
            int u=e[i].u,v=e[i].v;
            T l=lca(u,v);
    //        T l=solve(i);
            if(e[i].w==l.mx)mnn=min(mnn,e[i].w-l.nmx);
            else mnn=min(mnn,e[i].w-l.mx);
        }
        printf("%lld",ans+mnn);
        return 0;
    }
  • 相关阅读:
    Leetcode 238. Product of Array Except Self
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 290. Word Pattern
    Leetcode 205. Isomorphic Strings
    Leetcode 107. Binary Tree Level Order Traversal II
    Leetcode 102. Binary Tree Level Order Traversal
    三目运算符
    简单判断案例— 分支结构的应用
    用switch判断月份的练习
    java基本打印练习《我行我素购物系统》
  • 原文地址:https://www.cnblogs.com/Zinn/p/9275905.html
Copyright © 2011-2022 走看看