【LOJ】#121. 「離線可過」動態圖連通性
阿新 • • 發佈:2018-12-12
題解
和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('\n') #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; }