zoukankan      html  css  js  c++  java
  • [BZOJ 2049] [Sdoi2008] Cave 洞穴勘测 【LCT】

    题目链接:BZOJ - 2049

    题目分析

    LCT的基本模型,包括 Link ,Cut 操作和判断两个点是否在同一棵树内。

    Link(x, y) : Make_Root(x); Splay(x); Father[x] = y;

    Cut(x, y) : Make_Root(x); Access(y); 断掉 y 和 Son[y][0]; 注意修改 Son[y][0] 的 isRoot 和 Father

    判断 x, y 是否在同一棵数内,我们就看两个点所在树的根是否相同,使用 Find_Root();

    Find_Root(x) : Access(x); Splay(x); while (Son[x][0] != 0) x = Son[x][0]; 然后 x 就是树根了。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    inline void Read(int &Num)
    {
    	char c = getchar();
    	bool Neg = false;
    	while (c < '0' || c > '9')
    	{
    		if (c == '-') Neg = true;
    		c = getchar();
    	}
    	Num = c - '0'; c = getchar();
    	while (c >= '0' && c <= '9')
    	{
    		Num = Num * 10 + c - '0';
    		c = getchar();
    	}
    	if (Neg) Num = -Num;
    }
    
    const int MaxN = 10000 + 5;
    
    int n, m;
    int Father[MaxN], Son[MaxN][2];
    
    bool isRoot[MaxN], Rev[MaxN];
    
    inline void Reverse(int x)
    {
    	Rev[x] = !Rev[x];
    	swap(Son[x][0], Son[x][1]);
    }
    
    inline void PushDown(int x)
    {
    	if (!Rev[x]) return;
    	Rev[x] = false;
    	if (Son[x][0]) Reverse(Son[x][0]);
    	if (Son[x][1]) Reverse(Son[x][1]);
    }
    
    void Rotate(int x)
    {
    	int y = Father[x], f;
    	PushDown(y); PushDown(x);
    	if (x == Son[y][0]) f = 1;
    	else f = 0;
    	if (isRoot[y])
    	{
    		isRoot[y] = false;
    		isRoot[x] = true;
    	}
    	else
    	{
    		if (y == Son[Father[y]][0]) Son[Father[y]][0] = x;
    		else Son[Father[y]][1] = x;
    	}
    	Father[x] = Father[y];
    	Son[y][f ^ 1] = Son[x][f];
    	if (Son[x][f]) Father[Son[x][f]] = y;
    	Son[x][f] = y;
    	Father[y] = x;
    }
    
    void Splay(int x)
    {
    	int y;
    	while (!isRoot[x])
    	{
    		y = Father[x];
    		if (isRoot[y])
    		{
    			Rotate(x);
    			break;
    		}
    		if (y == Son[Father[y]][0])
    		{
    			if (x == Son[y][0])
    			{
    				Rotate(y);
    				Rotate(x);
    			}
    			else
    			{
    				Rotate(x);
    				Rotate(x);
    			}
    		}
    		else
    		{
    			if (x == Son[y][1])
    			{
    				Rotate(y);
    				Rotate(x);
    			}
    			else
    			{
    				Rotate(x);
    				Rotate(x);
    			}
    		}
    	}
    }
    
    int Access(int x)
    {
    	int y = 0;
    	while (x != 0)
    	{
    		Splay(x);
    		PushDown(x);
    		isRoot[Son[x][1]] = true;
    		Son[x][1] = y;
    		if (y) isRoot[y] = false;
    		y = x;
    		x = Father[x];
    	}
    	return y;
    }
    
    void Make_Root(int x)
    {
    	int t = Access(x);
    	Reverse(t);
    }
    
    int Find_Root(int x)
    {
    	int t = Access(x);
    	while (Son[t][0] != 0) t = Son[t][0];
    	return t;
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; ++i) 
    	{
    		isRoot[i] = true;
    		Father[i] = 0;
    	}
    	char Str[10];	
    	int a, b, x, y;
    	for (int i = 1; i <= m; ++i)
    	{
    		scanf("%s", Str);
    		Read(a); Read(b);
    		if (strcmp(Str, "Connect") == 0)
    		{
    			Make_Root(a);
    			Splay(a);
    			Father[a] = b;
    		}
    		else if (strcmp(Str, "Destroy") == 0)
    		{
    			Make_Root(a);
    			Access(b);
    			Splay(b);
    			PushDown(b);
    			isRoot[Son[b][0]] = true;
    			Father[Son[b][0]] = 0;
    			Son[b][0] = 0;
    		}
    		else
    		{
    			x = Find_Root(a);
    			y = Find_Root(b);
    			if (x == y) printf("Yes
    ");
    			else printf("No
    ");
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Ubuntu 12.10下为Firefox安装Adobe Flash Player
    oracle同时操作两个实例,如何进行切换操作?
    Ubuntu 12.10下为Firefox安装Adobe Flash Player
    Ubuntu11.10 安装oracle 11g
    oracle忘记system和sys账户的密码怎么办?
    linux 搭建java开发环境
    Oracle 笔记 day04
    节约网络带宽的设计策略
    集群化服务器
    01 基础概念(实战Linux Shell编程与服务器管理)
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4445502.html
Copyright © 2011-2022 走看看