zoukankan      html  css  js  c++  java
  • bzoj3669: [Noi2014]魔法森林 lct版

    先上题目 bzoj3669: [Noi2014]魔法森林

    这道题首先每一条边都有一个a,b 我们按a从小到大排序 每次将一条路劲入队 当然这道题权在边上 所以我们将边化为点去连接他的两个端点

    当然某两个点我用的是并查集维护 其实也可以在树上直接查询 但是这样比较方便 同时我们维护某个点极其子树的最大值所在的位置 每入一条边 如果两个端点已经联通就找出权值的边删掉之后连上新的边顺便更新答案 如果没联通就直接连上边就好 这样就解决问题了

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int M=200007,inf=0x3f3f3f3f;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m,ans=inf;
    int c[M][2],fa[M],p[M];
    int mx[M],v[M],rev[M];
    bool isrt(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    struct node{int a,b,u,v;}e[M];
    bool cmp(node a,node b){return a.a<b.a;}
    int find(int x){return p[x]==x?x:p[x]=find(p[x]);}
    void up(int x){
        int l=c[x][0],r=c[x][1];
        mx[x]=x;
        if(v[mx[l]]>v[mx[x]]) mx[x]=mx[l];
        if(v[mx[r]]>v[mx[x]]) mx[x]=mx[r];
    }
    void down(int x){
        int l=c[x][0],r=c[x][1];
        if(rev[x]){
            rev[x]=0; rev[l]^=1; rev[r]^=1;
            swap(c[x][0],c[x][1]);
        }
    }
    void rotate(int x){
        int y=fa[x],z=fa[y],l=0,r=1;
        if(c[y][1]==x) l=1,r=0;
        if(!isrt(y)) c[z][c[z][1]==y]=x;
        fa[y]=x; fa[x]=z; fa[c[x][r]]=y;
        c[y][l]=c[x][r]; c[x][r]=y;
        up(y); up(x);
    }
    int st[M],top;
    void splay(int x){
        st[++top]=x; for(int i=x;!isrt(i);i=fa[i]) st[++top]=fa[i];
        while(top) down(st[top--]);
        while(!isrt(x)){
            int y=fa[x],z=fa[y];
            if(!isrt(y)){
                if(c[z][0]==y^c[y][0]==x) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    void acs(int x0){
        for(int x=x0,y=0;x;splay(x),c[x][1]=y,up(x),y=x,x=fa[x]);
        splay(x0);
    }
    void mrt(int x){acs(x); rev[x]^=1;}
    void link(int x,int y){mrt(x); fa[x]=y;}
    void cut(int x,int y){mrt(x); acs(y); c[y][0]=fa[x]=0; up(y);}
    int push_max(int x,int y){mrt(x); acs(y); return mx[y];}
    int main()
    {
        n=read(); m=read();
        for(int i=1;i<=n;i++) p[i]=i;
        for(int i=1;i<=m;i++) e[i].u=read(),e[i].v=read(),e[i].a=read(),e[i].b=read();
        sort(e+1,e+1+m,cmp);
        for(int i=1;i<=m;i++){
            int from=e[i].u,to=e[i].v,a=e[i].a,b=e[i].b;
            if(find(from)==find(to)){
                int now=push_max(from,to);
                if(v[now]>b){cut(now,e[now-n].v); cut(now,e[now-n].u);}
                else{
                    if(find(1)==find(n)) ans=min(ans,a+v[push_max(1,n)]);
                    continue;
                }
            }
            else p[find(from)]=find(to);
            v[i+n]=b; mx[i+n]=i+n;
            link(from,i+n); link(to,i+n);
            if(find(1)==find(n)) ans=min(ans,a+v[push_max(1,n)]);
        }
        if(ans==inf) printf("-1
    ");
        else printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    eclipse中文乱码问题解决方案
    修改Tomcat的JDK目录
    Tomcat 5.5 修改服务器的侦听端口
    HTML DOM教程 27HTML DOM Button 对象
    HTML DOM教程 24HTML DOM Frameset 对象
    Navicat for MySQL v8.0.27 的注册码
    HTML DOM教程 25HTML DOM IFrame 对象
    Tomcat 5.5 的下载和安装
    android manifest相关属性
    ubuntu10.04 下 eclipse 小结
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7003757.html
Copyright © 2011-2022 走看看