[Luo Gu P2387] [NOI2014] Enchanted Forest

Title Description: https://www.luogu.org/problem/P2387

 

Analysis: is the maximum value the minimum requirements of the subject, the first thought two points, but there are two variables do not, then obviously think of a Greedy: UV for two points, edges between them a small value, b value is also small side definitely better. So we first side by a value, then by b value to maintain the minimum spanning tree. For a newly inserted side, if it has appeared in the unruly minimum spanning tree, we query the largest ring in the side edge is greater than this, if it is, then cut off the original that edge. So what I Fengyun how to maintain minimum spanning tree it? Obviously the LCT. But we want to maintain that boundary, how do it? A routine is to build a multi-point, then the value of the point assigned to the right side, the beginning and end, respectively, can be connected to this edge.

 

Details: 1. no details, do not write like hanging.

Attach Code:

#include <cstdio> 
#include <the iostream> 
#include <algorithm> 
 the using  namespace STD; 

// Given a graph, each edge has two ab & weights, to find a path to the starting point of
 // such that this path on a maximum value and the maximum value and the minimum b 

const  int MAXN = 50005 , MAXM = 200005 ;
 int n-, m;
 struct Edge {
     int U, V, a, b; 
} Edge [MAXM]; 
int FA [MAXM ];
 struct the Node {
     int max, Val, Son [ 2 ], FA;
     BOOL flag_reverse; 
} Node [MAXM << . 1 ];
 int ans=0x3f3f3f;
int stk[MAXM<<1];

inline int read(){
    int ret=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-f;c=getchar();}
    while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    return ret*f;
}

void readIn(int i){
    edge[i].u=read();edge[i].v=read();edge[i].a=read();edge[i].b=read();
    edge[i+1].u=edge[i].u;edge[i+1].v=edge[i].v;edge[i+1].a=edge[i].a;edge[i+1].b=edge[i].b;
}

int union_find(int x){
    if(x==fa[x]) return x;
    else return fa[x]=union_find(fa[x]);
}

void update(int x){
    node[x].max=x;
    int lson=node[x].son[0],rson=node[x].son[1];
    if(lson&&node[node[lson].max].val>node[node[x].max].val) node[x].max=node[lson].max;
    if(rson&&node[node[rson].max].val>node[node[x].max].val) node[x].max=node[rson].max;
}

void pushdown(int x){
    if(node[x].flag_reverse){
        int lson=node[x].son[0],rson=node[x].son[1];
        node[lson].flag_reverse^=1;
        node[rson].flag_reverse^=1;
        node[x].flag_reverse^=1;
        swap(node[x].son[0],node[x].son[1]);        
    } 
}

int get(int x){
    return x==node[node[x].fa].son[0]||x==node[node[x].fa].son[1];
}

int check(int x){
    return x==node[node[x].fa].son[1];
}

void rotate(int x){
    int y=node[x].fa,z=node[y].fa,d=check(x),xx=node[x].son[d^1];
    node[y].son[d]=xx;if(xx) node[xx].fa=y;
    if(get(y)) node[z].son[check(y)]=x;node[x].fa=z;
    node[x].son[d^1]=y;node[y].fa=x;
    update(y);update(x);
}

void splay(int x){
    int y=x,top=0;stk[++top]=y;
    while(get(y)) stk[++top]=y=node[y].fa;
    while(top) pushdown(stk[top--]);
    while(get(x)){
        int y=node[x].fa;
        if(get(y))
            rotate(check(x)==check(y)?y:x);
        rotate(x);
    }
} 

void access(int x){
    int xx=0;
    while(x){
        splay(x);
        node[x].son[1]=xx;
        xx=x;
        update(x);
        x=node[x].fa;
    }
}

int find(int x){
    access(x);splay(x);
    while(node[x].son[0]) x=node[x].son[0];
    return x;
}

void make_root(int x){
    access(x);splay(x);
    node[x].flag_reverse^=1;
}

void link(int x,int y){
    make_root(x);if(find(y)!=x) node[x].fa=y;
}

void split(int x,int y){
    make_root(x);access(y);splay(y);
}

void cut(int x,int y){
    split(x,y);
    if(find(y)==x&&!node[x].son[1]&&node[x].fa==y)
        node[x].fa=node[y].son[0]=0;
}

int query(int x,int y){
    split(x,y);
    return node[y].max;
}

void work(){
    for(int i=1;i<=m;++i) fa[i]=i;
    for(int i=1;i<=m;i++){
        int u=edge[i].u,v=edge[i].v;
        if(union_find(u)==union_find(v)){
            int t=query(u,v);
            if(edge[i].b<node[t].val){
                cut(t,edge[t-n].u);
                cut(t,edge[t-n].v);
            }
            else{
                if(union_find(1)==union_find(n))
                    ans=min(ans,edge[i].a+node[query(1,n)].val);
                continue;
            }
        }
        else fa[union_find(u)]=union_find(v);
        node[i+n].max=i+n;node[i+n].val=edge[i].b;
        link(u,i+n);link(i+n,v);
        if(union_find(1)==union_find(n))
            ans=min(ans,edge[i].a+node[query(1,n)].val);
    }
    if(ans!=0x3f3f3f)
        printf("%d",ans);
    else 
        printf("-1"); 
}

bool cmp(Edge A,Edge B){
    return A.a<B.a;
}

int main(){
    n=read();m=read();m<<=1;
    for(int i=1;i<=m;i+=2) readIn(i);
    sort(edge+1,edge+m+1,cmp);
    work();
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/JoshDun/p/11324299.html