洛谷 P4180 【模板】严格次小生成树[BJWC2010] LCT

首次采用了压行,感觉还不错。

Code:

// luogu-judger-enable-o2
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
void setIO(string a){
    freopen((a+".in").c_str(),"r",stdin);
    //freopen((a+".out").c_str(),"w",stdout);
}
#define inf 1000000000
#define maxn 300007
int ch[maxn][2],f[maxn],val[maxn],max1[maxn],max2[maxn];
int sta[maxn],tag[maxn];
int lson(int x){ return ch[x][0]; }
int rson(int x){ return ch[x][1]; }
int get(int x){ return ch[f[x]][1]==x; }
int isRoot(int x){ return !(ch[f[x]][0]==x||ch[f[x]][1]==x); }
void mark(int x){ if(x) swap(ch[x][0],ch[x][1]),tag[x]^=1; }
void pushdown(int x){ if(tag[x]) mark(lson(x)), mark(rson(x)), tag[x]=0; }
void pushup(int x){
    if(max1[lson(x)]>max1[rson(x)]) max1[x]=max1[lson(x)], max2[x]=max(max2[lson(x)],max1[rson(x)]);
    else if(max1[lson(x)]<max1[rson(x)]) max1[x]=max1[rson(x)], max2[x]=max(max2[rson(x)],max1[lson(x)]);
    else max1[x]=max1[lson(x)], max2[x]=max(max2[lson(x)],max2[rson(x)]);

    if(val[x]>max1[x]) max2[x]=max1[x],max1[x]=val[x];
    else if(val[x]!=max1[x]) max2[x]=max(max2[x],val[x]);
}

void rotate(int x) {
    int old=f[x],oldf=f[old],which=get(x);
    if(!isRoot(old)) ch[oldf][ch[oldf][1]==old]=x;
    ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
    ch[x][which^1]=old,f[old]=x,f[x]=oldf;
    pushup(old),pushup(x);
}

void splay(int x){
    int v=0,u=x;
    sta[++v]=u; 
    while(!isRoot(u)) sta[++v]=f[u],u=f[u];
    while(v) pushdown(sta[v--]);
    u=f[u];
    for(int fa;(fa=f[x])!=u;rotate(x))
        if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x);
}

void Access(int x){ for(int y=0;x;y=x,x=f[x]) splay(x),ch[x][1]=y,pushup(x); }
void makeRoot(int x){ Access(x),splay(x),mark(x); }
void split(int x,int y){ makeRoot(x),Access(y),splay(y); }
struct Union_Find{
    int p[maxn];
    int find(int x){ return p[x]==x?x:p[x]=find(p[x]);}
    void init(){for(int i=1;i<maxn;++i)p[i]=i;}
    void merge(int x,int y){ int a=find(x),b=find(y); if(a!=b) p[a]=b; }
}tree;
struct Edge{
    int u,v,c;
    Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}
}edges[maxn];
bool cmp(Edge e1,Edge e2){ return e1.c<e2.c; }
int main(){   
    //setIO("input");
    tree.init();
    int n,m,cnt,x,y,ans=inf;
    long long sum=0;
    scanf("%d%d",&n,&m),cnt=n;
    for(int i=1;i<=m;++i) scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].c);
    sort(edges+1,edges+1+m,cmp);
    for(int i=1;i<=m;++i){
        x=edges[i].u,y=edges[i].v;
        if(tree.find(x)==tree.find(y)){
            split(x,y);
            ans=min(ans,edges[i].c-(max1[y]>=edges[i].c?max2[y]:max1[y])); 
        }
        else{
            makeRoot(x);
            f[f[x]=++cnt]=y;
            max1[cnt]=val[cnt]=edges[i].c;
            sum+=edges[i].c;
            tree.merge(x,y);
        }
    }
    printf("%lld",sum+ans);
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/10083064.html