bzoj4229 选择

URL

https://www.lydsy.com/JudgeOnline/problem.php?id=4229

简要题意

给一个无向图。
多次询问,每次删掉一条边,或者询问两个点是否在同一个边双连通分量内。

解法

倒着做。
先只保留所有操作结束后剩下的边,建出边双连通分量对应的森林。
然后倒序加边,每次要么是合并两个树,要么是把一条路径上的点都缩到同一个双连通分量里。

实现

#include 
using namespace std;

#define rng(i,a,b) for(int i=int(a);i=int(a);i--)
#define rep(i,b) rng(i,0,b)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define mp make_pair
#define a first
#define b second
#define all(x) (x).begin(),(x).end()
#define si(x) int((x).size())

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair pi;
typedef vector vi;

template void chmax(t&a,u b){if(a void chmin(t&a,u b){if(b>(istream&i,Q&q){
        i>>q.tp>>q.x>>q.y;
        q.x--,q.y--;
        if(q.x>q.y)swap(q.x,q.y);
        return i;
    }
};
struct E{
    int s;
    bool tp;
    E(){}
    E(int a,int b,bool t):s(a^b),tp(t){}
    int other(int a){
        return a^s;
    }
};

Q qs[vmax];
unionfind u1,u2;

vector info;
vi g[vmax];
int ce=0;

void make(int a,int b,bool t){
    g[a].pb(si(info));
    g[b].pb(si(info));
    info.pb(E(a,b,t));
}

int id[vmax],lo[vmax],cur;
int par[vmax],dep[vmax];

int res[vmax];

void dfs(int v,int p){
    id[v]=lo[v]=cur++;
    rep(z,si(g[v])){
        int e=g[v][z];
        if(e==p)continue;
        int to=info[e].other(v);
        bool tp=info[e].tp;

        if(id[to]==-1){
            dep[to]=dep[v]+1;
            par[to]=v;
            dfs(to,e);
            if(!tp){
                chmin(lo[v],lo[to]);
                if(lo[to]<=id[v])u2.mg(to,v);
            }
        }else if(!tp){
            chmin(lo[v],id[to]);
        }
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n,m,q;cin>>n>>m>>q;
    multiset es;
    rep(i,m){
        int a,b;cin>>a>>b;
        a--,b--;
        if(a>b)swap(a,b);
        es.insert(pi(a,b));
    }

    rep(i,q){
        cin>>qs[i];
        if(qs[i].tp=='Z')
            es.erase(es.find(pi(qs[i].x,qs[i].y)));
    }

    u1=unionfind(n);
    u2=unionfind(n);
    {
        for(multiset::iterator it=es.begin();it!=es.end();++it){
            int a=it->a,b=it->b;
            u1.mg(a,b);
            make(a,b,false);
        }
        unionfind tmp=u1;
        gnr(i,0,q)if(qs[i].tp=='Z'){
            int a=qs[i].x,b=qs[i].y;
            if(tmp.same(a,b))continue;
            tmp.mg(a,b);
            make(a,b,true);
        }

        fill(id,id+n,-1);
        fill(par,par+n,-1);
        rep(i,n)if(id[i]==-1)dfs(i,-1);
        assert(n==cur);
    }

    gnr(i,0,q){
        int a=qs[i].x,b=qs[i].y;
        if(qs[i].tp=='Z'){
            if(!u1.same(a,b)){
                if(dep[a]

你可能感兴趣的:(bzoj4229 选择)