• P4180 【模板】严格次小生成树[BJWC2010]


      之前写的一道题,突然看到就来发一篇博客。

      大致思路就是首先找到最小生成树,再枚举每一条不在这个树里的边,加上后肯定就形成一个环,我们就要在这个环上断一条边。

      新加的边 >= 这条路径上最大值。(反证法)

      如果新加的边 > 这条路径上最大值,则ans - 最大值 + 新的权值,否则 - 次大值 + 新的值。

      因此我们需要维护最大值,次大值即可。  

      以及,我的代码并不支持重边,提前筛掉。

      下面是代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define int long long
    #define maxn 200010
    #define inf 9999999999999999
    int f[maxn][25],M[maxn][25],s[maxn][25],head[maxn];
    int fa[maxn],dep[maxn],in[maxn*6],o[maxn];
    int n,m,cnt,tot,MAX,SEC_MAX,ans=inf,size,map[1000][1000];
    struct node
    {
        int to,nxt,w;
    } q[maxn*2];
    struct K
    {
        int l,r,w,id;
    } k[maxn*6];
    int find(int a)
    {
        return a==fa[a] ? a : fa[a]=find(fa[a]);
    }
    void add(int a,int b,int c)
    {
        q[++cnt].to=b;
        q[cnt].nxt=head[a];
        head[a]=cnt;
        q[cnt].w=c;
    }
    bool cmp(K a,K b)
    {
        return a.w<b.w;
    }
    void Kruscal()
    {
        int num=0;
        for(int i=1; i<=m; i++)
        {
            int L=k[i].l;
            int R=k[i].r;
            int faL=find(L);
            int faR=find(R);
            if(faL==faR) continue;
            num++;
            fa[faL]=faR;
            add(k[i].l,k[i].r,k[i].w);
            add(k[i].r,k[i].l,k[i].w);
            in[k[i].id]=1;
            size+=k[i].w;
            if(num==n-1) break;
        }
    }
    void dfs(int u,int ff)
    {
        //cout<<u<<endl;
        dep[u]=dep[ff]+1;
        for(int i=0; i<=20; i++)
        {
            f[u][i+1]=f[f[u][i]][i];
            M[u][i+1]=max(M[u][i],M[f[u][i]][i]);
            int sec1=min(M[u][i],M[f[u][i]][i]);
            int sec2=max(s[u][i],s[f[u][i]][i]);
            s[u][i+1]=max(sec1,sec2);
        }
        for(int i=head[u]; i; i=q[i].nxt)
        {
            int v=q[i].to;
            if(v==ff) continue;
            M[v][0]=q[i].w;
            f[v][0]=u;
            dfs(v,u);
        }
    }
    void Deal(int x,int i)
    {
        if(MAX!=M[x][i])
        {
            if(MAX<M[x][i])
            {
                SEC_MAX=max(MAX,s[x][i]);
                MAX=M[x][i];
            }
            else
                SEC_MAX=max(SEC_MAX,M[x][i]);
        }
    }
    void DD(int x)
    {
        if(M[x][0]>MAX)
        {
            SEC_MAX=MAX;
            MAX=M[x][0];
        }
        else if(M[x][0]>SEC_MAX)
            SEC_MAX=M[x][0];
    }
    void LCA(int x,int y)
    {
        MAX=SEC_MAX=0;
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=20; i>=0; i--)
        {
            if(dep[f[x][i]]>=dep[y])
            {
                Deal(x,i);
                x=f[x][i];
            }
            if(x==y) return ;
        }
        for(int i=20; i>=0; i--)
        {
            if(f[x][i]!=f[y][i])
            {
                Deal(x,i);
                Deal(y,i);
                x=f[x][i];
                y=f[y][i];
            }
        }
        //cout<<SEC_MAX<<" "<<MAX<<" ";
        DD(x);
        DD(y);
        return ;
    }
    void SEC_Kruscal()
    {
        for(int i=1; i<=m; i++)
        {
            if(in[k[i].id]) continue;
            int x=k[i].l,y=k[i].r;
            int W=k[i].w;
            LCA(x,y);
            if(W==MAX) ans=min(ans,size-SEC_MAX+W);
            else ans=min(ans,size-MAX+W);
            //cout<<k[i].l<<" "<<k[i].r<<" "<<SEC_MAX<<" "<<MAX<<endl;
        }
        printf("%lld
    ",ans);
    }
    main()
    {
        scanf("%lld%lld",&n,&m);
        //if(n==7) {printf("242
    ");return 0;}
        for(int i=1; i<=n; i++)
            fa[i]=i;
        for(int i=1; i<=m; i++)
        {
            int a,b,c;
            scanf("%lld%lld%lld",&a,&b,&c);
            k[++tot].l=a;
            k[tot].r=b;
            k[tot].w=c;
            k[tot].id=tot;
        }
        sort(k+1,k+m+1,cmp);
        Kruscal();
        //for(int i=1;i<=m;i++)
        //printf("%d %d
    ",k[i].w,in[k[i].id]);
        dfs(1,0);
        SEC_Kruscal();
        //cout<<s[3][0]<<endl;
        return 0;
    }
  • 相关阅读:
    hdoj_1556Color the ball
    wchar_t与char转换(总结)
    算法艺术——网络最大流
    poj_3268Silver Cow Party
    poj_2352Stars
    BellmanFord模板
    saas模式
    什么是管道
    什么是CMMI
    saas模式
  • 原文地址:https://www.cnblogs.com/popo-black-cat/p/10686795.html
Copyright © 2020-2023  润新知