严格次小生成树

顾名思义。

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

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

实际上,有

结论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
*/
原文地址:https://www.cnblogs.com/Miracevin/p/10143741.html