P2387 [NOI2014]魔法森林

和最小差值生成树差不多

都是用lct维护生成树的题目

本题可以以a排序,再维护b(通常这种二维变量的题都差不多这样,先排序一维)

然后我tm竟然rotate手误打错了一点...调了好久..

然后关于pushup:关于最大值,最小值一类的信息要在pushup中赋初值,而异或和之类的可以不用

就是说不可以用引用中写法的来写..

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+7;
const int M=1e5+7;
int n,m,st[N+M],tot,ans=1<<30,w[N+M];
struct edge{
    int a,b,u,v;
    bool operator <(const edge &x)const {
        return a<x.a;
    }
}e[M];
struct tree{
    int ch[2],fa,mx=-1,id=-1;
    bool rev;
}t[N+M];
void pushup(int x) {
    t[x].mx=w[x],t[x].id=x;
    if(t[x].ch[0]&&t[t[x].ch[0]].mx>t[x].mx) t[x].mx=t[t[x].ch[0]].mx,t[x].id=t[t[x].ch[0]].id;
    if(t[x].ch[1]&&t[t[x].ch[1]].mx>t[x].mx) t[x].mx=t[t[x].ch[1]].mx,t[x].id=t[t[x].ch[1]].id;
}
void rev(int x){
    swap(t[x].ch[0],t[x].ch[1]);
    t[x].rev^=1;
}
void pushdown(int x){
    if(t[x].rev){
        if(t[x].ch[0])rev(t[x].ch[0]);
        if(t[x].ch[1])rev(t[x].ch[1]);
        t[x].rev=0;
    }
}
bool nroot(int x){
    return (t[t[x].fa].ch[0]==x)||(t[t[x].fa].ch[1]==x);
}
void rotate(int x){
    int y=t[x].fa;
    int z=t[y].fa;
    bool k=t[y].ch[1]==x;
    if(nroot(y))t[z].ch[t[z].ch[1]==y]=x;
    t[x].fa=z;
    t[y].ch[k]=t[x].ch[k^1];
    t[t[x].ch[k^1]].fa=y;
    t[x].ch[k^1]=y;
    t[y].fa=x;
    pushup(y);
    pushup(x);
}
void splay(int x){
    int y=0,z=x;
    st[++y]=z;
    while(nroot(z))st[++y]=z=t[z].fa;
    while(y)pushdown(st[y--]);
    while(nroot(x)){
        y=t[x].fa;
        z=t[y].fa;
        if(nroot(y))
            (t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y);
        rotate(x);
    }
}
void access(int x){
    for(int y=0;x;y=x,x=t[x].fa){
        splay(x);
        t[x].ch[1]=y;
        pushup(x);
    }
}
void makeroot(int x){
    access(x);
    splay(x);
    rev(x);
}
void split(int x,int y){
    makeroot(x);
    access(y);
    splay(y);
}
int findroot(int x){
    access(x);
    splay(x);
    while(t[x].ch[0])x=t[x].ch[0];
    splay(x);
    return x;
}
void link(int x,int y){
    splay(x);
    t[x].fa=y;
}
bool check(int x,int y){
    makeroot(x);
    return findroot(y)==x;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b);
    }
    sort(e+1,e+1+m);
    for(int i=1;i<=m;i++){
        int u=e[i].u;
        int v=e[i].v;
        //t[i+n].mx=e[i].b,t[i+n].id=i+n;
        w[i+n]=e[i].b;
        if(u==v)continue;
        if(!check(u,v)){
            link(u,i+n),link(i+n,v);
        }
        else {
            split(u,v);
            int now=t[v].id,maxx=t[v].mx;
            if(e[i].b>maxx)continue;
            splay(now),t[t[now].ch[0]].fa=t[t[now].ch[1]].fa=0;
            link(u,i+n),link(i+n,v);
        }
        if(check(1,n)){
            split(1,n);
            ans=min(ans,t[n].mx+e[i].a);
        }
    }
    if(ans==1<<30)puts("-1");
    else printf("%d\n",ans);
    return 0;
}

 

posted @ 2019-05-09 17:25  天才美少女雪乃  阅读(152)  评论(0编辑  收藏  举报