• bzoj2594: [Wc2006]水管局长数据加强版


    居然1A,思路清晰的好处。

    题目不再解释;

    题目要求维护两点间最小的路径所经过边的权值最大值,很显然,这东西肯定是在MST上;

    Kruskal跑出MST,就可以在树上随便搞;

    但题目有删边要求,删边不好做,干脆反过来做成加边;

    用LCT维护一下两点间最大的边就好了;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<cstdlib>
    #include<ctime>
    #include<algorithm>
    using namespace std;
    #define mid ((l+r)>>1)
    #define LL long long
    #define FILE "dealing"
    #define up(i,j,n) for(LL i=(j);i<=(n);i++)
    #define pii pair<int,int>
    int read(){
        int x=0,f=1,ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return f*x;
    }
    const int maxn=300010,inf=100000000,mod=998244353;
    int n,m,q;
    struct edge{int x,y,v;}b[1001000];
    bool cmp(edge a,edge b){return a.v<b.v;}
    struct node{int y,next,v;}e[2000000],k[2000000];
    int len,linkk[2000000],cnt,Link[2000000],fa[maxn],x[maxn],y[maxn],ans[maxn],Max[maxn],cnt_point,w[maxn],f[maxn][2],val[maxn];
    void insert(node* e,int* linkk,int& len,int x,int y,int v){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;e[len].v=v;}
    int ch[maxn],u[maxn],v[maxn];
    namespace Kruskal{
        int fa[maxn];
        int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
        void kruskal(){
            cnt_point=n;
            bool flag=0;
            up(i,1,n)fa[i]=i;
            up(i,1,m){
                flag=0;
                for(int j=Link[b[i].x];j;j=k[j].next)
                    if(k[j].y==b[i].y){
                        val[k[j].v]=b[i].v;
                        flag=1;
                        break;
                    }
                for(int j=Link[b[i].y];j;j=k[j].next)
                    if(k[j].y==b[i].x){
                        val[k[j].v]=b[i].v;
                        flag=1;
                        break;
                    }
                if(flag)continue;
                getfa(b[i].x),getfa(b[i].y);
                if(fa[b[i].x]==fa[b[i].y])continue;
                fa[b[i].x]=fa[b[i].y];
                cnt_point++;
                f[cnt_point][0]=b[i].x,f[cnt_point][1]=b[i].y;
                insert(e,linkk,len,b[i].x,cnt_point,b[i].v);
                insert(e,linkk,len,cnt_point,b[i].x,b[i].v);
                insert(e,linkk,len,b[i].y,cnt_point,b[i].v);
                insert(e,linkk,len,cnt_point,b[i].y,b[i].v);
            }
        }
    };
    namespace DFS{
        void dfs(int x){
            for(int i=linkk[x];i;i=e[i].next){
                if(e[i].y==fa[x])continue;
                if(x>n)w[x]=e[i].v;
                Max[x]=x;
                fa[e[i].y]=x;
                dfs(e[i].y);
            }
        }
    };
    namespace LCT{
        int c[maxn][2],rev[maxn],q[maxn],top;
        void reve(int o){rev[o]^=1,swap(c[o][0],c[o][1]);}
        void pushdown(int o){if(rev[o])reve(c[o][0]),reve(c[o][1]),rev[o]^=1;}
        void updata(int o){
            Max[o]=o;
            if(w[Max[c[o][1]]]>w[Max[o]])Max[o]=Max[c[o][1]];
            if(w[Max[c[o][0]]]>w[Max[o]])Max[o]=Max[c[o][0]];
        }
        bool isroot(int o){return c[fa[o]][0]!=o&&c[fa[o]][1]!=o;}
        void rotate(int x){
            int y=fa[x],z=fa[y],d=(c[y][1]==x);
            if(!isroot(y))c[z][c[z][1]==y]=x;
            fa[y]=x;fa[x]=z;fa[c[x][d^1]]=y;
            c[y][d]=c[x][d^1];c[x][d^1]=y;
            updata(y),updata(x);
        }
        void splay(int x){
            q[++top]=x;
            for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
            while(top)pushdown(q[top--]);
            while(!isroot(x)){
                int y=fa[x],z=fa[y];
                if(!isroot(y)){
                    if(c[y][1]==x^c[z][1]==y)rotate(x);
                    else rotate(y);
                }
                rotate(x);
            }
        }
        void access(int x){
            for(int t=0;x;t=x,x=fa[x])
                splay(x),c[x][1]=t,updata(x);
        }
        void makeroot(int x){
            access(x);splay(x);reve(x);
        }
        void cut(int x,int y){
            makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;updata(y);
        }
        void link(int x,int y){
            makeroot(x);fa[x]=y;
        }
    };
    int main(){
        freopen(FILE".in","r",stdin);
        freopen(FILE".out","w",stdout);
        n=read(),m=read(),q=read();
        up(i,1,m)b[i].x=read(),b[i].y=read(),b[i].v=read();
        sort(b+1,b+m+1,cmp);
        up(i,1,q)ch[i]=read(),x[i]=read(),y[i]=read();
        up(i,1,q)if(ch[i]==2){
            insert(k,Link,cnt,x[i],y[i],i);
            insert(k,Link,cnt,y[i],x[i],i);
        }
        Kruskal::kruskal();
        DFS::dfs(1);
        for(int i=q;i>0;i--){
            if(ch[i]==1){
                LCT::makeroot(x[i]),LCT::access(y[i]),LCT::splay(y[i]);
                ans[i]=w[Max[y[i]]];
            }
            if(ch[i]==2){
                LCT::makeroot(x[i]),LCT::access(y[i]),LCT::splay(y[i]);
                int t=Max[y[i]];
                if(val[i]<w[t]){
                    LCT::cut(f[t][0],t);LCT::cut(f[t][1],t);
                    cnt_point++;
                    f[cnt_point][0]=x[i],f[cnt_point][1]=y[i];
                    w[cnt_point]=val[i];
                    LCT::link(x[i],cnt_point);
                    LCT::link(y[i],cnt_point);
                }
            }
        }
        up(i,1,q)if(ch[i]==1)printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Intellij IDEA 打开文件tab数量限制的调整
    Mysql处理中文乱码的问题
    MIT算法导论笔记
    算法导论-排序(一)-插入排序、归并排序
    leetcode题解:Search for a Range (已排序数组范围查找)
    leetcode 题解:Merge Sorted Array(两个已排序数组归并)
    leetcode题解:Construct Binary Tree from Inorder and Postorder Traversal(根据中序和后序遍历构造二叉树)
    leetcode题解:Construct Binary Tree from Preorder and Inorder Traversal (根据前序和中序遍历构造二叉树)
    c++11 std::prev、std::next、std::advance与auto 使用
    (转)指针的引用(*&)与指针的指针(**)
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6337376.html
Copyright © 2020-2023  润新知