zoukankan      html  css  js  c++  java
  • CF938G Shortest Path Queries

    题目描述

    题解

    考虑到删边或者改边权不好操作,于是我们可以线段树分治,这样就只有加边并且边权确定。

    考虑一下如何求一张图上一个点到另一个点的最小异或值,那这是一个经典问题,考虑到图上的环的异或值都可以取出,并且三个有交集的环两个异或后就是第三个,所以我们如果对于一棵树加上一条非树边,那就直接把这个环的异或值扔到线性基里即可。维护树的形态可以用可持久化并查集,即启发式合并即可。

    效率: $O(nlog^2n)$ 。

    代码

    #include <bits/stdc++.h>
    #define M make_pair
    using namespace std;
    const int N=4e5+5;
    int n,m,t,c,U[N],Q,V[N],f[N],s[N],a[20][30],p[N];
    map<pair<int,int>,int>mp;
    struct O{int x,y,z;}e[N],q[N];
    vector<O>g[N<<1],b[N<<1];
    void ins(int x,int y,int z){
        e[++c]=(O){x,y,z};
        U[c]=t+1;V[c]=-1;mp[M(x,y)]=c;
    }
    int F(int x){while(x!=f[x]) x=f[x];return x;}
    int G(int x){int v=0;while(x!=f[x]) v^=p[x],x=f[x];return v;}
    #define Ls k<<1
    #define Rs k<<1|1
    #define mid ((l+r)>>1)
    void upd(int k,int l,int r,int L,int R,int i){
        if (L<=l && r<=R){
            g[k].push_back(e[i]);return;
        }
        if (mid>=L) upd(Ls,l,mid,L,R,i);
        if (mid<R) upd(Rs,mid+1,r,L,R,i);
    }
    void qry(int k,int l,int r,int d){
        for (int i=0;i<30;i++) a[d][i]=a[d-1][i];
        int z=g[k].size(),w;
        for (int x,y,u,v,i=0;i<z;i++){
            u=g[k][i].x;v=g[k][i].y;
            w=g[k][i].z;x=F(u);y=F(v);w^=G(u)^G(v);
            if (x==y){
                for (int i=29;~i;i--)
                    if (w&(1<<i)){
                        if (!a[d][i]){
                            a[d][i]=w;break;
                        }
                        w^=a[d][i];
                    }
                continue;
            }
            if (s[x]>s[y]) swap(x,y),swap(u,v);
            b[k].push_back((O){x,y,s[y]});
            p[x]=w;f[x]=y;s[y]+=s[x];
        }
        if (l==r){
            w=G(q[l].x)^G(q[l].y);
            for (int i=29;~i;i--)
                w=min(w,w^a[d][i]);
            printf("%d
    ",w);
        }
        else qry(Ls,l,mid,d+1),qry(Rs,mid+1,r,d+1);
        z=b[k].size();
        for (int u,i=z-1;~i;i--)
            s[b[k][i].y]=b[k][i].z,
            p[u=b[k][i].x]=0,f[u]=u;
    }
    int main(){
        cin>>n>>m;
        for (int x,y,z,i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            if (x>y) swap(x,y);ins(x,y,z);
        }
        cin>>Q;
        for (int op,x,y,z;Q--;){
            scanf("%d%d%d",&op,&x,&y);
            if (x>y) swap(x,y);
            if (op<2) scanf("%d",&z),
                V[mp[M(x,y)]]=t,ins(x,y,z);
            else if (op<3)
                V[mp[M(x,y)]]=t,mp[M(x,y)]=0;
            else q[++t]=(O){x,y,0};
        }
        for (int i=1;i<=c;i++){
            if (!~V[i]) V[i]=t;
            if (U[i]<=V[i]) upd(1,1,t,U[i],V[i],i);
        }
        for (int i=1;i<=n;i++) f[i]=i,s[i]=1;
        qry(1,1,t,1);return 0;
    }
  • 相关阅读:
    Docker中查看Mysql数据库中的各环境参数
    Hbase shell 输入无法使用退格键删除解决办法
    HBase启动时报错:/bin/java: No such file or directory6/bin/../bin/hbase: line 412: /usr/local/jdk1.8.0_152/bin/java
    SSH无密码验证
    详解分布式应用程序协调服务Zookeeper
    zookeeper的原理及使用
    Hadoop、Yarn和vcpu资源的配置
    一文让您全面了解清楚HBase数据库的所有知识点,值得收藏!
    基于Docker一键部署大规模Hadoop集群及设计思路
    PHP ServerPush (推送) 技术的探讨【转】
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12451722.html
Copyright © 2011-2022 走看看