zoukankan      html  css  js  c++  java
  • 「WC 2006」水管局长

    题目链接

    戳我

    (Solution)

    这道题实际上是维护一个最小生成树,因为正的搞不好搞,所以反着搞会比较好,现将没有没删掉的边留下来生成一颗最小生成树,再加边就好了,现在(LCT)

    来看看怎么维护

    对于一个最小生成树,加一条边后会是一个环,在环上删掉一个最大的边,还是一个最小生成树。所以我们对于加边只要判断这条边和最小生成树上最大边的大小,如果小于,则将这条边加入,原最小生成树上最大的边删除,如果大于不需要管他。

    但是(LCT)只能维护点权,不能维护边权,不妨将这个边看成点即可

    加入((x,y)的边)就是(link(x,id),link(y,id),id)为这条边的编号
    (cut)同理

    (Code)

    #include<bits/stdc++.h>
    #define rg register
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    inline int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    struct node {
        int fa,v,lazy,ch[2];
    }a[1100001];
    int v[1100001],pre[100001];
    map<int,int> f[100001];
    int vis[1000001];
    inline bool nroot(int x){
        return a[a[x].fa].ch[0]==x||a[a[x].fa].ch[1]==x;
    }
    inline int max(int x,int y){
        return v[x]>v[y]?x:y;
    }
    inline void pushup(int x){
        a[x].v=max(a[a[x].ch[0]].v,max(a[a[x].ch[1]].v,x));
    }
    inline void work(int x){
        int t=a[x].ch[0];
        a[x].ch[0]=a[x].ch[1],a[x].ch[1]=t,a[x].lazy^=1;
    }
    inline void pushdown(int x){
        if(a[x].lazy)
            work(x),a[a[x].ch[0]].lazy^=1,a[a[x].ch[1]].lazy^=1;
    }
    inline void rotate(int x){
        int y=a[x].fa,z=a[y].fa,k=(a[y].ch[1]==x);
        if(nroot(y)) a[z].ch[a[z].ch[1]==y]=x;
        a[x].fa=z,a[y].ch[k]=a[x].ch[k^1],a[a[x].ch[k^1]].fa=y;
        a[x].ch[k^1]=y,a[y].fa=x;
        pushup(x),pushup(y);
    }
    inline void down(int x){
        if(nroot(x)) down(a[x].fa);
        pushdown(x);
    }
    inline void splay(int x){
        down(x);
        while(nroot(x)){
            int y=a[x].fa,z=a[y].fa;
            if(nroot(y))
                (a[y].ch[1]==x)^(a[z].ch[1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        int y=0;
        while(x) splay(x),a[x].ch[1]=y,pushup(y=x),x=a[x].fa;
    }
    inline void makeroot(int x){
        access(x),splay(x),a[x].lazy^=1;
    }
    inline void splix(int x,int y){
        makeroot(x),access(y),splay(y);
    }
    inline int findroot(int x){
        access(x),splay(x);
        while(a[x].ch[0]) pushdown(x),x=a[x].ch[0];
        splay(x);
        return x;
    }
    inline void link(int x,int y){
        makeroot(x);
        if(findroot(y)!=x)
            a[x].fa=y;
    }
    inline void cut(int x,int y){
        makeroot(x);
        if(findroot(y)!=x||a[y].fa!=x||a[y].ch[0]) return ;
        a[y].fa=a[x].ch[1]=0,pushup(x);
    }
    struct node1{
        int x,y,z;
    }b[1000001];
    inline bool cmp(const node1 & a , const node1 & b ){
        return a.z<b.z;
    }
    inline int find(int x){
        return pre[x]==x?x:pre[x]=find(pre[x]);
    }
    int X[100001],Y[100001],opt[100001],n,m,q,ans[100001],tot;
    inline void MST(){
        for(int i=1;i<=n;i++)
            pre[i]=i;
        for(int i=1;i<=m;i++){
            int fx=find(b[i].x),fy=find(b[i].y);
            if(!vis[i]&&fx!=fy)
                link(b[i].x,i+n),link(b[i].y,i+n),pre[fx]=fy;
        }
    }
    int main(){
        n=read(),m=read(),q=read();
        for(rg int i=1;i<=m;i++)
            b[i].x=read(),b[i].y=read(),b[i].z=read();
        sort(b+1,b+1+m,cmp);
        for(rg int i=1;i<=m;i++)
            f[b[i].x][b[i].y]=f[b[i].y][b[i].x]=i+n,v[i+n]=b[i].z;
        for(rg int i=1;i<=q;i++){
            opt[i]=read(),X[i]=read(),Y[i]=read();
            if(opt[i]==2) vis[f[X[i]][Y[i]]-n]=1;
        }
        MST();
        for(rg int i=q;i>=1;i--){
            splix(X[i],Y[i]);
            if(opt[i]==1)
                ans[++tot]=v[a[Y[i]].v];
            else{
                if(v[a[Y[i]].v]>v[f[X[i]][Y[i]]]){
                    int x=a[Y[i]].v;
                    cut(b[x-n].x,x),cut(b[x-n].y,x),link(X[i],f[X[i]][Y[i]]),link(Y[i],f[X[i]][Y[i]]);
                }
            }
        }
        for(rg int i=tot;i>=1;i--)
            printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    2016.07.24
    这个月
    PL/SQL: numeric or value error: character to number conversion error
    java下double相乘精度丢失问题
    Oracle中实现find_in_set
    oracle中,改变表名和字段名的大小写
    Unknown entity XXX
    Incorrect column count: expected 1, actual 5
    负数的二进制表示
    【Android】Android单例模式及使用单例模式实现自己的HttpClient工具类
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10728771.html
Copyright © 2011-2022 走看看