zoukankan      html  css  js  c++  java
  • 严格次小生成树

    顾名思义。

    生成树,边权和严格小于最小生成树

    一定和最小生成树有关系。

    实际上,有

    结论1:严格次小生成树只在最小生成树上改动一条边

    证明:

    改动一条边有意义的话,必然改完这条边,总和变大。

    那么这至少是严格次小生成树的最大值。再改一条也没有意义。

    结论2:改动的那条边w,一定是新加入的那条边覆盖的树链的最大值或者严格次大值。

    证明:

    w比最大值大的话,一定扔掉这个最大值

    相等的话,一定扔掉严格次大值。

    如果不存在严格次大值,那么不可能。也符合“严格”的题意。

    kruscal跑MST

    枚举剩下没有加入的边,要求出这条链上的最大值和严格次大值

    可以倍增,树剖,LCT等等。

    倍增显然最优。

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

    #include<bits/stdc++.h>
    #define il inline
    #define reg register int
    #define numb (ch^'0')
    #define int long long
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=100000+5;
    const int M=300000+5;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    int n,m;
    struct node{
        int x,y;
        ll z;
        bool in;
        bool friend operator <(node a,node b){
            return a.z<b.z;
        }
    }bian[M];
    int ff[N];
    int fin(int x){
        return ff[x]==x?x:ff[x]=fin(ff[x]);
    }
    int fa[N][20],mx[N][20],cmx[N][20];
    ll sum;
    struct edge{
        int nxt,to;
        int val;
    }e[2*N];
    int hd[N],cnt;
    void add(int x,int y,int z){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        e[cnt].val=z;
        hd[x]=cnt;
    }
    int dep[N];
    ll ans;
    void dfs(int x,int d){
        dep[x]=d;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y==fa[x][0]) continue;
            fa[y][0]=x;
            mx[y][0]=e[i].val;
            cmx[y][0]=-inf;
            dfs(y,d+1);
        }
    }
    int query(int x,int y,ll z){//z is val of new edge
        int big=-inf;
        if(dep[x]<dep[y]) swap(x,y);
        for(reg j=19;j>=0;--j){
            if(dep[fa[x][j]]>=dep[y]){
                if(mx[x][j]!=z) big=max(big,mx[x][j]);
                else big=max(big,cmx[x][j]);
                x=fa[x][j];
            }
        }
        if(x==y){
            return z-big;
        }
        for(reg j=19;j>=0;--j){
            if(fa[x][j]!=fa[y][j]){
                if(mx[x][j]!=z) big=max(big,mx[x][j]);
                else big=max(big,cmx[x][j]);
                x=fa[x][j];
                
                if(mx[y][j]!=z) big=max(big,mx[y][j]);
                else big=max(big,cmx[y][j]);
                y=fa[y][j];
            }
        }
        int j=0;
                if(mx[x][j]!=z) big=max(big,mx[x][j]);
                else big=max(big,cmx[x][j]);
                
                if(mx[y][j]!=z) big=max(big,mx[y][j]);
                else big=max(big,cmx[y][j]);
        return z-big;
    }
    int main(){
        rd(n);rd(m);
        memset(mx,-1,sizeof mx);
        memset(cmx,-1,sizeof cmx);
        int x,y,z;
        for(reg i=1;i<=m;++i){
            rd(x);rd(y);rd(z);
            bian[i].x=x,bian[i].y=y;bian[i].z=z;
        }
        for(reg i=1;i<=n;++i) ff[i]=i;
        sort(bian+1,bian+m+1);
        for(reg i=1;i<=m;++i){
            int x=bian[i].x,y=bian[i].y;
            int k1=fin(x),k2=fin(y);
            if(k1!=k2){
                ff[k1]=k2;
                bian[i].in=1;
                sum+=bian[i].z;
                add(bian[i].x,bian[i].y,bian[i].z);
                add(bian[i].y,bian[i].x,bian[i].z);
            }
        }
        //cout<<" sum "<<sum<<endl;
        dep[0]=-1;
        dfs(1,1);
        for(reg j=1;j<=19;++j){
            for(reg i=1;i<=n;++i){
                fa[i][j]=fa[fa[i][j-1]][j-1];
                int big=mx[fa[i][j-1]][j-1],cbig=cmx[fa[i][j-1]][j-1];
                mx[i][j]=max(mx[i][j-1],big);
                cmx[i][j]=max(cmx[i][j-1],cbig);
                if(mx[i][j-1]>big) cmx[i][j]=max(cmx[i][j],big);
                if(mx[i][j-1]<big) cmx[i][j]=max(cmx[i][j],mx[i][j-1]);
            } 
        }
        ans=0x3f3f3f3f3f3f3f3f;
        for(reg i=1;i<=m;++i){
            if(!bian[i].in){
                int tmp=query(bian[i].x,bian[i].y,bian[i].z);
                ans=min(ans,sum+tmp);
            }
        }
        printf("%lld",ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/19 14:36:23
    */
  • 相关阅读:
    一本名副其实的 Web架构“圣经”——关于《HTTP权威指南》
    图灵生日会——纪念阿兰图灵诞辰100周年及图灵公司七周年线下交流会
    跟着图灵听课去!(六月)
    “电梯演讲”最精炼、贴切的语言
    送你一把开启演讲之路的钥匙——《演讲的艺术》
    翻译是一份严谨的工作——关于HTTP中文翻译的讨论
    浪潮之巅作者吴军推荐序——《推荐系统实践》
    如何到达永生?揭示科学之美
    软件行业大牛告诉你何谓成功?
    C#线程系列讲座(3):线程池和文件下载服务器
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10143741.html
Copyright © 2011-2022 走看看