• XJOI网上同步测试DAY14 T3


    思路:tarjan把桥找出来,然后缩点,注意这里的缩点是:如果两个点之间的连边不是桥,那么就把他们缩起来,然后用一个lct维护,对于每个询问,如果官道连接的是两个联通块的话,就把他们连起来,否则我们就把u到v的路径全部染色成0

    最后只要询问缩点完的S到缩点完的T的路径上有多少是1就是答案了,最后复杂度:O(nlogn)

    至于为什么这么做:因为我们要找必经过的边,这不就是桥吗,那我们先预处理出原来图的桥,然后把图转变成树,之后对于官道来说,它只要是连接了两个在同一个联通块里的点,就表明这段路绝对不可能是必经之路,而对于连接两个连通分量的边,那么它就是新的桥啊!因此它要被新建成为lct中的一条边。

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    struct edge{
        int u,v;
    }e[600005];
    int n,m;
    int tot,go[600005],next[600005],first[600005],Id[600005];
    int ch[600005][2],sz,num,sum[600005],w[600005],col[600005],tag[600005];
    int dfn[600005],low[600005],pd[600005],vis[600005];
    int st[600005],c[600005],belong[600005],fa[600005];
    int rev[600005],size[600005];
    int read(){
        int t=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
        while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
        return t*f;
    }
    void insert(int x,int y,int id){
        tot++;
        go[tot]=y;
        next[tot]=first[x];
        first[x]=tot;
        Id[tot]=id;
    }
    void add(int x,int y,int id){
        insert(x,y,id);
        insert(y,x,id);
    }
    void tarjan(int x,int Fa){
        dfn[x]=low[x]=++sz;
        for (int i=first[x];i;i=next[i])
         if (Id[i]!=Fa){
                int pur=go[i];
                if (!dfn[pur]){
                    tarjan(pur,Id[i]);
                    low[x]=std::min(low[x],low[pur]);
                    if (low[pur]>dfn[x]) pd[Id[i]]=1;
                }else{
                    low[x]=std::min(low[x],dfn[pur]);
                }
         }
    }
    void bfs(int x){
        int h=1,t=1;c[1]=x;vis[x]=1;belong[x]=++num;
        while (h<=t){
            int now=c[h++];
            for (int i=first[now];i;i=next[i]){
                int pur=go[i];
                if (pd[Id[i]]||vis[pur]) continue;
                c[++t]=pur;
                vis[pur]=1;
                belong[pur]=num;
            }
        }
    }
    bool isroot(int x){
        return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
    }
    void pushdown(int x){
        int l=ch[x][0],r=ch[x][1];
        if (tag[x]!=0){
            int id=(tag[x]==1)?0:1;
            if (l)tag[l]=tag[x];
            if (r)tag[r]=tag[x];
            if (l&&w[l]) col[l]=id;
            if (r&&w[r]) col[r]=id;
            if (l) sum[l]=size[l]*id;
            if (r) sum[r]=size[r]*id;
            tag[x]=0;
        }
        if (rev[x]){
            rev[l]^=1;
            rev[r]^=1;
            rev[x]=0;
            std::swap(ch[x][0],ch[x][1]);
        }
    }
    void updata(int x){
        int l=ch[x][0],r=ch[x][1];
        if (w[x]==0){
            col[x]=0;sum[x]=0;size[x]=0;
            if (l) sum[x]+=sum[l],size[x]+=size[l];
            if (r) sum[x]+=sum[r],size[x]+=size[r];
            return;
        }
        sum[x]=col[x];size[x]=1;
        if (l) sum[x]+=sum[l],size[x]+=size[l];
        if (r) sum[x]+=sum[r],size[x]+=size[r];
    }
    void rotate(int x){
        int y=fa[x],z=fa[y],l,r;
        if (ch[y][0]==x) l=0;else l=1;r=l^1;
        if (!isroot(y)){
           if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;    
        }
        fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
        ch[y][l]=ch[x][r];ch[x][r]=y;
        updata(y);updata(x);
    }
    void splay(int x){
        int top=1;st[1]=x;
        for (int i=x;!isroot(i);i=fa[i])
         st[++top]=fa[i];
        for (int i=top;i;i--)
         pushdown(st[i]);
        while (!isroot(x)){
            int y=fa[x],z=fa[y];
            if (!isroot(y)){
                if (ch[y][0]==x^ch[z][0]==y) rotate(x);
                else rotate(y);
            }
            rotate(x);
        } 
        //updata(x); 
    }
    void access(int x){
        for (int t=0;x;t=x,x=fa[x]){
            splay(x);
            ch[x][1]=t;
            updata(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];
        return x;
    }
    void cut(int x,int y){
        makeroot(x);access(y);splay(y);
        ch[y][0]=fa[ch[y][0]]=0;
        updata(y);
    }
    void link(int x,int y){
        makeroot(x);fa[x]=y;
    }
    int main(){
        n=read();m=read();
        for (int i=1;i<=m;i++){
            e[i].u=read();e[i].v=read();
            add(e[i].u,e[i].v,i);
        }
        for (int i=1;i<=n;i++)
         if (!dfn[i]) tarjan(i,0);
        sz=0;num=0;
        for (int i=1;i<=n;i++)
         if (!vis[i]) bfs(i); 
        sz=num;
        for (int i=1;i<=m;i++)
         if (belong[e[i].u]!=belong[e[i].v]){
            sz++;col[sz]=1;tag[sz]=0;sum[sz]=1;w[sz]=1;
            size[sz]=1;
            link(sz,belong[e[i].u]);
            link(sz,belong[e[i].v]);
         } 
        int q=read();
        while (q--){
            int S=read(),T=read(),Num=read(),cnt=0;
            S=belong[S],T=belong[T];
            for (int i=1;i<=Num;i++){
                e[i].u=read();e[i].v=read();
                e[i].u=belong[e[i].u];
                e[i].v=belong[e[i].v];
            }
            for (int i=1;i<=Num;i++){
                if (e[i].u==e[i].v) continue;
                if (find(e[i].u)!=find(e[i].v)){
                    w[sz+i]=1;sum[sz+i]=1;
                    tag[sz+i]=0;col[sz+i]=1;
                    size[sz+i]=1;
                    link(e[i].u,sz+i);
                    link(e[i].v,sz+i);
                    pd[i]=1;
                }else{
                    pd[i]=0;
                    makeroot(e[i].u);access(e[i].v);splay(e[i].v);
                    tag[e[i].v]=1;
                }
            }
            if (find(S)!=find(T)){
                puts("-1");
            }else{
            makeroot(S);access(T);splay(T);
            printf("%d
    ",sum[T]);
            }
            for (int i=Num;i>=1;i--){
                if (e[i].u==e[i].v) continue;
                if (pd[i]==1){
                    cut(e[i].u,sz+i);
                    cut(e[i].v,sz+i);
                }else{
                    makeroot(e[i].u);access(e[i].v);splay(e[i].v);
                    tag[e[i].v]=-1;
                }
            }
        }
    }
  • 相关阅读:
    现代3D图形编程学习-关于本书
    极简单之爬虫入门
    前端学HTTP之网络基础
    用canvas 实现个图片三角化(LOW POLY)效果
    移动前端—图片压缩上传实践
    nodejs实现Websocket的数据接收发送
    nodejs学习之实现简易路由
    nodejs学习之实现http数据转发
    canvas粒子demo
    nodejs简易实现一下bigpipe
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5674150.html
Copyright © 2020-2023  润新知