• 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;
    }
  • 相关阅读:
    ATL正则表达式库使用
    用InternetOpen()的下载者
    获取IWebBrowser2指针的方法
    IE自动登陆-Navigate篇
    用WinInet开发Internet客户端应用指南
    VC中的GetKeyState和GetAsyncKeyState的区别
    通过IWebBrowser2的Navigate2来打开网页,怎样判断网页是否全部加载完毕
    利用IWebBrowser2接口的Navigate2方法实现Http POST传输
    IE撤销机制CtrlZ功能会在由于Js动态改变页面元素失效
    Web安全渗透测试之信息搜集篇(下)
  • 原文地址:https://www.cnblogs.com/Zinn/p/9275905.html
Copyright © 2020-2023  润新知