• NOI2014魔法森林


    题目链接

    把边按a从小到大排序,枚举一条边,相当于只考虑<=ai的边,根据b做一个最小生成树再算答案。

    用lct维护这个最小生成树,要加入的这条边若会形成环,则找到x到y路径上最大的b,与当前边比较看加还是不加(加就把那条边删掉)。

    维护边权可以把边看做一个点,点权为边权,并与原边的两个端点连边。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<map>
    #define P puts("lala")
    #define cp cerr<<"lala"<<endl
    #define ln putchar('
    ')
    #define sp putchar(' ')
    #define pb push_back
    #define fi first
    #define se second 
    #define mkp make_pair
    using namespace std;
    typedef pair<int,int> pii;
    inline void read(int &re)
    {
        char ch=getchar();int g=1;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        re=0;
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
        re*=g;
    }
    typedef long long ll;
    inline void read(ll &re)
    {
        char ch=getchar();ll g=1;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        re=0;
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48ll,ch=getchar();
        re*=g;
    }
    const int N=150050;
    struct node
    {
        int x,y,a,b;
        node() {x=0;y=0;a=0;b=0;}
    }e[N];
    bool operator < (node a,node b)
    {
        return a.a<b.a;
    }
    int n,m;
    int maxv[N],maxwh[N],fa[N],ch[N][2],val[N];
    bool rev[N];
    inline bool ge(int x) {return ch[fa[x]][1]==x;}
    inline bool isroot(int x) {return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x;}
    inline void up(int x)
    {
        if(!x) return ;
        maxv[x]=val[x]; maxwh[x]=x;
        if(ch[x][0]) 
        {
            if(maxv[ch[x][0]]>maxv[x]) maxwh[x]=maxwh[ch[x][0]],maxv[x]=maxv[ch[x][0]];
        }
        if(ch[x][1]) 
        {
            if(maxv[ch[x][1]]>maxv[x]) maxwh[x]=maxwh[ch[x][1]],maxv[x]=maxv[ch[x][1]];
        }
    }
    inline void pushdown(int x)
    {
        if(x&&rev[x])
        {
            if(ch[x][0]) rev[ch[x][0]]^=1;
            if(ch[x][1]) rev[ch[x][1]]^=1;
            rev[x]=0;
            swap(ch[x][0],ch[x][1]);
        }
    }
    inline void rotate(int x)
    {
        int f=fa[x],g=fa[f],wh=ge(x);
        if(!isroot(f)) ch[g][ch[g][1]==f]=x;
        ch[f][wh]=ch[x][wh^1]; fa[ch[f][wh]]=f;
        ch[x][wh^1]=f; fa[f]=x;
        fa[x]=g;
        up(f);up(x);
    }
    int st[N],top=0;
    void splay(int x)
    {
        top=0;st[++top]=x;
        for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
        for(int i=top;i;--i) pushdown(st[i]);
    
        for(int f;(f=fa[x])&&!isroot(x);rotate(x))
            if(!isroot(f)) rotate(ge(x)==ge(f)?f:x);
    }
    void access(int x)
    {
        for(int t=0;x;t=x,x=fa[x])
            splay(x),ch[x][1]=t,up(x);
    }
    void makeroot(int x)
    {
        access(x); splay(x); rev[x]^=1;
    }
    int find(int x)
    {
        access(x); splay(x);
        while(ch[x][0]) x=ch[x][0]; splay(x);
        return x;
    }
    void link(int x,int y)
    {
        makeroot(x); fa[x]=y;
    }
    void cut(int x,int y)
    {
        makeroot(x); access(y); splay(y);
        fa[x]=0; ch[y][0]=0; up(y);
    }
    int query(int x,int y)
    {
        makeroot(x); access(y); splay(y);
        return maxv[y];
    }
    
    
    const int inf=0x3f3f3f3f;
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    #endif
        int i,j,opt,T;
        read(n);read(m);
        for(i=1;i<=m;++i)
        {
            read(e[i].x);read(e[i].y);read(e[i].a);read(e[i].b);
        }
        sort(e+1,e+1+m);
        int ans=inf;
        for(i=1;i<=n+m;++i) maxwh[i]=i;
        for(i=1;i<=m;++i)
        {
            int x=e[i].x,y=e[i].y;
            if(x==y) continue;
            val[i+n]=e[i].b; maxv[i+n]=e[i].b;
            if(find(x)!=find(y)) link(x,i+n),link(i+n,y);
            else
            {
                makeroot(x); access(y); splay(y);
                int k=maxwh[y]-n;
                if(e[k].b<e[i].b) continue;
                cut(e[k].x,k+n); cut(k+n,e[k].y);
                link(x,i+n); link(i+n,y);
            }
            if(find(1)==find(n)) ans=min(ans,e[i].a+query(1,n));
        }
        printf("%d",ans==inf?-1:ans);
        return 0;
    }
    /*
    
    */
  • 相关阅读:
    linux下查找文件中空行的行号
    JavaScript:jklyDB
    Chart:Amcharts
    Chart-template
    Miscellaneos:ISV
    杂项-模板
    Error-MVCr:找到了多个与 URL 匹配的控制器类型。如果多个控制器上的特性路由与请求的 URL 匹配,则可能会发生这种情况。
    Error-MVC:HTTP Error 500.19
    ASP.NET 网站管理工具
    HTML:Browser 对象
  • 原文地址:https://www.cnblogs.com/thkkk/p/7856266.html
Copyright © 2020-2023  润新知