[AHOI2005]LANE 航线规划
Posted on 2015年1月17日 17:31/****************************************\ * Author : ztx * Title : [AHOI2005]LANE 航线规划 * ALG : Tarjan+LCT+离线+瞎搞 * CMT : "无论航线如何被破坏,任意时刻任意两个星球都能够相互到达": * 连通图,缩点后不是森林 * "在整个数据中,任意两个星球之间最多只可能存在一条直接的航线": * 无重边 * Time : \****************************************/
/****************************************\ * Author : ztx * Title : [AHOI2005]LANE 航线规划 * ALG : Tarjan+LCT+离线+瞎搞 * CMT : "无论航线如何被破坏,任意时刻任意两个星球都能够相互到达": * 连通图,缩点后不是森林 * "在整个数据中,任意两个星球之间最多只可能存在一条直接的航线": * 无重边 * Time : \****************************************/ #include <cstdio> int CH , NEG ; inline int GETCHAR() { static const int LEN = 1<<15 ; static char BUF[LEN] , *S = BUF , *T = BUF ; if (S == T) { T = (S=BUF)+fread(BUF , 1 , LEN , stdin) ; if (S == T) return EOF ; } return *S ++ ; } inline void read(int& ret) { ret = NEG = 0 ; while (CH=GETCHAR() , CH<'!') ; if (CH == '-') NEG = true , CH = GETCHAR() ; while (ret=(ret<<1)+(ret<<3)+CH-'0' , CH=GETCHAR() , CH>'!') ; if (NEG) ret = -ret ; } #include <algorithm> #include <cstring> #define maxn 30010LL #define maxm 1000010LL #define maxe 2000010LL #define maxq 40010LL #define infi 0x3f3f3f3fLL int n , m , Q ; struct FST { int to , next ; } e1[maxe] , e2[maxe] ; int star1[maxn] = {0} , star2[maxn] = {0} , tote1 = 0 , tote2 = 0 ; void AddEdge(int u , int v) { e1[++tote1].to = v ; e1[tote1].next = star1[u] ; star1[u] = tote1 ; e1[++tote1].to = u ; e1[tote1].next = star1[v] ; star1[v] = tote1 ; } void BCCAddEdge(int u , int v) { e2[++tote2].to = v ; e2[tote2].next = star2[u] ; star2[u] = tote2 ; e2[++tote2].to = u ; e2[tote2].next = star2[v] ; star2[v] = tote2 ; } struct QUE { int cmd , u , v , id , ans ; } q[maxq] ; struct EDGE { int u , v , del ; EDGE() { del = false ; } } e[maxm] ; int tote = 0 ; bool CmpT(const EDGE& a , const EDGE&b) { if (a.u == b.u) return a.v < b.v ; return a.u < b.u ; } int L , M , R ; inline int Bsearch(int u , int v) { L = 1 , R = m ; while (R-L > 1) { /* (L , R] */ M = L+(R-L)/2 ; if (e[M].u<u || (e[M].u==u&&e[M].v<v)) L = M ; else R = M ; } return R ; } int f[maxn] = {0} ; inline int GetAnc(int u) { return f[u] ? f[u] = GetAnc(f[u]) : u ; } inline void Union(int u , int v) { u = GetAnc(u) , v = GetAnc(v) ; if (u != v) f[u] = v ; } int fa[maxn] = {0} , ch[maxn][2] = {0} ; int size[maxn] = {0} ; bool rev[maxn] = {0} ; #define null 0LL #define left(u) ch[u][0] #define right(u) ch[u][1] template<typename T>inline void Exchange(T&a , T&b) { T c=a;a=b;b=c; } inline bool Isrt(int u) { fa[u] = GetAnc(fa[u]) ; return (fa[u]==null)||(left(fa[u])!=u&&right(fa[u])!=u) ; } inline void Maintain(int u) { size[u] = 1 ; if (left(u)) size[u] += size[left(u)] ; if (right(u)) size[u] += size[right(u)] ; } inline void Clear(int u) { if (!u) return ; if (!Isrt(u)) Clear(fa[u]) ; if (rev[u]) { rev[u] = false ; rev[left(u)] ^= true ; rev[right(u)] ^= true ; Exchange(left(u) , right(u)) ; } } inline void zig(int x) { /* right rotate */ int y = fa[x] = GetAnc(fa[x]) , z = fa[y] = GetAnc(fa[y]) ; if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ; fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ; Maintain(y) , Maintain(x) ; } inline void zag(int x) { /* left rotate */ int y = fa[x] = GetAnc(fa[x]) , z = fa[y] = GetAnc(fa[y]) ; if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ; fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ; Maintain(y) , Maintain(x) ; } inline void Splay(int x) { Clear(x) ; int y , z ; while (!Isrt(x)) { y = fa[x] = GetAnc(fa[x]) , z = fa[y] = GetAnc(fa[y]) ; if (Isrt(y)) { if (left(y) == x) zig(x) ; else zag(x) ; } else { if (left(z) == y) { if (left(y) == x) zig(x) , zig(x) ; else zag(x) , zig(x) ; } else if (right(z) == y) { if (right(y) == x) zag(x) , zag(x) ; else zig(x) , zag(x) ; } } } } inline void Access(int u) { for (int v = null ; u ; u = fa[u] = GetAnc(fa[u])) Splay(u) , right(u) = v , v = u , Maintain(u) ; } inline void Makeroot(int u) { Access(u) , Splay(u) , rev[u] ^= true ; } int DFN[maxn] = {0} , LOW[maxn] = {0} , Belong[maxn] = {0} ; int Stap[maxn] = {0} ; int Stop , Bcnt , Dindex ; void DFS(int from , int u) { int v = 0 ; DFN[u] = LOW[u] = ++Dindex , Stap[++Stop] = u ; for (int p = star1[u] ; p ; p = e1[p].next) { v = e1[p].to ; if (from == v) continue ; if (!DFN[v]) { DFS(u , v) ; if (LOW[u] > LOW[v]) LOW[u] = LOW[v] ; if (DFN[u] < LOW[v]) { Bcnt ++ ; for ( ; Stap[Stop]!=v ; ) { Belong[Stap[Stop--]] = Bcnt ; } if (Stap[Stop]==v) Belong[Stap[Stop--]] = Bcnt ; } } else if (LOW[u] > DFN[v]) LOW[u] = DFN[v] ; } } void Tarjan() { Stop = Bcnt = Dindex = 0 ; memset(DFN , 0 , sizeof(DFN)) ; DFS(0 , 1) ; Bcnt ++ ; while (Stop) Belong[Stap[Stop--]] = Bcnt ; } bool vis[maxn] = {0} ; void BuildTree(int u) { if (vis[u]) return ; vis[u] = size[u] = 1 ; int p , v ; for (p = star2[u] ; p ; p = e2[p].next) { v = e2[p].to ; if (!vis[v]) { fa[v] = u ; BuildTree(v) ; } } } void Shrink(int from , int u) { if (!u) return ; if (from) Union(from , u) ; if (left(u)) Shrink(u , left(u)) ; if (right(u)) Shrink(u , right(u)) ; } int i , j , u , v , k , cnt = 0 ; int main() { #define READ #ifdef READ freopen("lane.in" ,"r",stdin ) ; freopen("lane.out","w",stdout) ; #endif /* 读入 */ read(n) , read(m) ; for (i = 1 ; i <= m ; i ++ ) { read(e[i].u) , read(e[i].v) ; if (e[i].u > e[i].v) Exchange(e[i].u , e[i].v) ; } /* 标记删除边 */ std::sort(e+1 , e+m+1 , CmpT) ; for (Q = 0 ; true ; ) { read(q[Q+1].cmd) ; if (q[Q+1].cmd == -1) break ; Q ++ ; read(q[Q].u) , read(q[Q].v) ; if (q[Q].cmd == 0) { if (q[Q].u > q[Q].v) Exchange(q[Q].u , q[Q].v) ; e[Bsearch(q[Q].u , q[Q].v)].del = true ; } } /* 对最终状态建图 */ for (i = 1 ; i <= m ; i ++ ) { if (e[i].del) continue ; AddEdge(e[i].u , e[i].v) ; } /* Tarjan求双联通分量 */ Tarjan() ; /* 对缩点后的联通块建图 */ for (i = 1 ; i <= m ; i ++ ) { if (e[i].del) continue ; u = Belong[e[i].u] , v = Belong[e[i].v] ; if (u != v) BCCAddEdge(u , v) ; } /* 对联通块建树 */ BuildTree(1) ; /* 回答询问 */ for (i = Q ; i ; i -- ) { u = GetAnc(Belong[q[i].u]) , v = GetAnc(Belong[q[i].v]) ; if (q[i].cmd == 1) { if (u == v) q[i].ans = 0 ; else { Makeroot(u) ; Access(v) , Splay(v) ; q[i].ans = size[v]-1 ; } } else if (u != v) { Makeroot(u) ; Access(v) , Splay(v) ; Shrink(null , v) ; fa[GetAnc(v)] = null ; } } for (i = 1 ; i <= Q ; i ++ ) if (q[i].cmd == 1) printf("%d\n", q[i].ans ) ; #ifdef READ fclose(stdin) ; fclose(stdout) ; #else getchar() ; getchar() ; #endif return 0 ; } /* 9 10 1 2 2 3 2 4 2 6 3 5 3 6 4 6 4 8 6 7 7 9 1 1 7 -1 20 35 1 2 1 3 1 4 1 8 1 11 1 16 2 3 2 5 2 7 2 11 2 19 3 8 3 9 3 10 4 6 4 9 4 11 4 15 4 19 5 8 5 11 5 16 5 17 6 12 6 14 6 16 7 10 7 11 7 13 7 19 8 9 9 18 10 14 14 20 17 18 0 8 9 0 1 8 1 7 20 1 5 15 1 12 14 0 6 16 1 14 8 1 17 2 0 6 14 1 5 6 0 17 18 1 14 9 -1 */