zoukankan      html  css  js  c++  java
  • 【LOJ】#121. 「离线可过」动态图连通性

    题解

    和BZOJ4025挺像的
    就是维护边权是时间的最大生成树

    删边直接删

    两点未联通时直接相连,两点联通则找两点间边权小的一条边删除即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 500005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N,M;
    int id[MAXN],tot,pos[MAXN + 5005];
    int op[MAXN],x[MAXN],y[MAXN];
    int t[5005][5005];
    namespace lct {
        struct node {
    	int lc,rc,fa,val,minq;
    	bool rev;
        }tr[MAXN * 2];
    #define lc(u) tr[u].lc
    #define rc(u) tr[u].rc
    #define fa(u) tr[u].fa
    #define val(u) tr[u].val
    #define minq(u) tr[u].minq
    #define rev(u) tr[u].rev
        void Init() {
    	val(0) = minq(0) = 0x7fffffff;
    	for(int i = 1 ; i <= N ; ++i) val(i) = minq(i) = M + 2;
        }
        void reverse(int u) {
    	swap(lc(u),rc(u));
    	rev(u) ^= 1;
        }
        void pushdown(int u) {
    	if(rev(u)) {
    	    reverse(lc(u));
    	    reverse(rc(u));
    	    rev(u) = 0;
    	}
        }
        void update(int u) {
    	minq(u) = val(u);
    	minq(u) = min(minq(u),minq(lc(u)));
    	minq(u) = min(minq(u),minq(rc(u)));
        }
        
        bool isRoot(int u) {
    	if(!fa(u)) return true;
    	else return rc(fa(u)) != u && lc(fa(u)) != u;
        }
        bool which(int u) {
    	return rc(fa(u)) == u;
        }
        void rotate(int u) {
    	int v = fa(u);
    	if(!isRoot(v)) {(v == lc(fa(v)) ? lc(fa(v)) : rc(fa(v))) = u;}
    	fa(u) = fa(v);fa(v) = u;
    	if(u == lc(v)) {lc(v) = rc(u);fa(rc(u)) = v;rc(u) = v;}
    	else {rc(v) = lc(u);fa(lc(u)) = v;lc(u) = v;}
    	update(v);
        }
        void Splay(int u) {
    	static int que[MAXN],qr;
    	qr = 0;int x;
    	for(x = u ; !isRoot(x) ; x = fa(x)) que[++qr] = x;
    	que[++qr] = x;
    	for(int i = qr ; i >= 1 ; --i) pushdown(que[i]);
    	while(!isRoot(u)) {
    	    if(!isRoot(fa(u))) {
    		if(which(fa(u)) == which(u)) rotate(fa(u));
    		else rotate(u);
    	    }
    	    rotate(u);
    	}
    	update(u);
        }
        void Access(int u) {
    	for(int x = 0 ; u ; x = u , u = fa(u)) {
    	    Splay(u);
    	    rc(u) = x;
    	    update(u);
    	}
        }
        void Makeroot(int u) {
    	Access(u);Splay(u);reverse(u);
        }
        void Link(int u,int v) {
    	Makeroot(u);Makeroot(v);Splay(v);fa(v) = u;
        }
        void Cut(int u,int v) {
    	Makeroot(u);Access(v);Splay(u);
    	if(rc(u) == v) {rc(u) = 0;fa(v) = 0;update(u);} 
        }
        int dfs(int u) {
    	if(val(u) == minq(u)) return u;
    	pushdown(u);
    	if(minq(lc(u)) == minq(u)) return dfs(lc(u));
    	else return dfs(rc(u));
        }
        int Query(int u,int v) {
    	Makeroot(u);Access(v);Splay(u);
    	return dfs(u);
        }
        bool Connected(int u,int v) {
    	Makeroot(u);Access(v);Splay(u);
    	int p = u;
    	while(rc(p)) p = rc(p);
    	if(p == v) return true;
    	return false;
        }
    }
    using lct::Link;
    using lct::Cut;
    using lct::Makeroot;
    using lct::Query;
    using lct::Connected;
    using lct::tr;
    void Init() {
        read(N);read(M);
        tot = N;
        lct::Init();
        for(int i = 1 ; i <= M ; ++i) {
    	read(op[i]);read(x[i]);read(y[i]);
    	if(op[i] == 0) {
    	    id[i] = ++tot;pos[tot] = i;
    	    t[x[i]][y[i]] = t[y[i]][x[i]] = id[i];
    	    tr[tot].val = tr[tot].minq = M + 1;
    	}
    	if(op[i] == 1) {
    	    int k = t[x[i]][y[i]];
    	    tr[k].val = tr[k].minq = i;
    	    id[i] = k;
    	}
        }
    }
    void Solve() {
        for(int i = 1 ; i <= M ; ++i) {
    	if(op[i] == 0) {
    	    if(!Connected(x[i],y[i])) {
    		Link(x[i],id[i]);Link(id[i],y[i]);
    	    }
    	    else {
    		int t = Query(x[i],y[i]);
    		if(lct::tr[t].val < lct::tr[id[i]].val) {
    		    Cut(t,x[pos[t]]);Cut(t,y[pos[t]]);
    		    Link(id[i],x[i]);Link(id[i],y[i]);
    		}
    	    }
    	}
    	else if(op[i] == 1) {
    	    Cut(x[i],id[i]);Cut(y[i],id[i]);
    	}
    	else {
    	    if(Connected(x[i],y[i])) puts("Y");
    	    else puts("N");
    	}
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    
  • 相关阅读:
    ThinkPHP 3.2.2 实现持久登录 ( 记住我 )
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 17 电话号码的字母组合
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10106757.html
Copyright © 2011-2022 走看看