C - Color the Tree(递归构造)

本文介绍了如何通过深度优先搜索(DFS)策略在多分支树结构中合并操作,以确保所有状态可达。关键步骤包括对子树答案数组的合并和状态路径的调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LINK

考虑只有一条链的情况,显然操作方案唯一,一路按下来即可

如果有两条链,设链一的状态为 s 1 , s 2 . . . s n s_1,s_2...s_n s1,s2...sn,链二的状态为 t 1 , t 2 . . . . t m t_1,t_2....t_m t1,t2....tm

所有状态都可以达到,形如

( s 1 , t 1 ) − ( s 2 , t 1 ) . . . ( s n , t 1 ) (s_1,t_1)-(s_2,t_1)...(s_n,t_1) (s1,t1)(s2,t1)...(sn,t1)

( s n , t 2 ) − ( s n − 1 , t 2 ) . . . ( s 1 , t 2 ) (s_n,t_2)-(s_{n-1},t_2)...(s_{1},t_2) (sn,t2)(sn1,t2)...(s1,t2)

( s 1 , t 3 ) − ( s 2 , t 3 ) . . . . . (s_1,t_3)-(s_2,t_3)..... (s1,t3)(s2,t3).....

如此往复,所有状态都可以达到

扩展到拥有多个分支,多个子树的复杂树形结构也是如此

先构造前两个子树的情况,然后把前两个子树当作一个子树,再构造和第三个子树的情况

设之前的 k k k个子树对应的答案数组为 a n s ans ans

显然 a n s . s i z e ( ) ans.size() ans.size()个操作对应全部的 a n s . s i z e ( ) + 1 ans.size()+1 ans.size()+1个状态

现在去 d f s dfs dfs k + 1 k+1 k+1个子树得到对应的答案数组 t e m p temp temp

现在我们来合并答案 e d ed ed数组使得所有状态都能取到

先令 e d = a n s ed=ans ed=ans,此时相当于取到

( s 1 , t 1 ) − ( s 2 , t 1 ) . . . ( s n , t 1 ) (s_1,t_1)-(s_2,t_1)...(s_n,t_1) (s1,t1)(s2,t1)...(sn,t1)

此时我们修改 t 1 t_1 t1 t 2 t_2 t2,然后倒序插入 a n s ans ans数组

( s n , t 2 ) − ( s n − 1 , t 2 ) . . . ( s 1 , t 2 ) (s_n,t_2)-(s_{n-1},t_2)...(s_{1},t_2) (sn,t2)(sn1,t2)...(s1,t2)

以此类推

最后需要再 e d ed ed数组的开头插入当前节点(子节点变色前提是父节点变色)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10; 
int n;
vector<int>vec[maxn];
void A_to_B(vector<int>& A,vector<int>& B )
{
	for(auto v:A )	B.push_back( v );
}
vector<int> dfs(int u)
{
	vector<int>ans;
	for( auto v:vec[u] )
	{
		vector<int>temp = ans, now = dfs( v ),invans;
		//temp是前k个子树的答案,合并为一个子树和now来 
		for(int i=ans.size()-1;i>=0;i--)	invans.push_back( ans[i] );
		for(int j=0;j<now.size();j++)
		{
			temp.push_back( now[j] ); 
			if( j&1 )	A_to_B( ans,temp );
			else	A_to_B( invans,temp );
		}
		ans = temp;
	}
	ans.insert(ans.begin(), u);
	return ans;
}
//vector<int> dfs(int u)
//{
//	vector<int>ans;
//	for( auto v:vec[u] )
//	{
//		vector<int>temp = ans, now = dfs( v ),invans;
//		//temp是前k个子树的答案,合并为一个子树和now来 
//		for(int i=ans.size()-1;i>=0;i--)	invans.push_back( ans[i] );
//		for(int j=0;j<now.size();j++)
//		{
//			temp.push_back( now[j] ); 
//			if( j&1 )	temp.insert( temp.end(),ans.begin(),ans.end() );
//			else	temp.insert( temp.end(),ans.rbegin(),ans.rend() );
//		}
//		ans = temp;
//	}
//	ans.insert(ans.begin(), u);
//	return ans;
//}
int main()
{
	cin >> n;
	for(int i=2;i<=n;i++)
	{
		int x; scanf("%d",&x);
		vec[x].push_back( i );
	}
	vector<int>ans = dfs(1);
	ans.erase( ans.begin() );
	cout << ans.size() << endl;
	for( auto v:ans )	printf("%d ",v );
}
using namespace std; enum { red, black }; template<typename T> struct treenode { treenode<T>* left; treenode<T>* right; treenode<T>* parent; int color; T data; treenode(T value) :left(nullptr), right(nullptr), color(red), data(value),parent(nullptr) {} }; template<typename T> class tree { private: treenode<T>* root; treenode<T>* nil; void insert( T value); void remove(T value); void exam(treenode<T>* node); void RR(treenode<T>* node); void LL(treenode<T>* node); void exam2(treenode<T>* node); void delete_x(treenode<T>* node); treenode<T>* finmin(treenode<T>* node); void rotateblack(treenode<T>* node,bool a); void _print(treenode<T>* node) { if (node != nil) { _print(node->left); cout << node->data <<" "<<node->color << endl; _print(node->right); } } void deletenode(treenode<T>* node) { if (node==nil)return; deletenode(node->left); deletenode(node->right); delete node; } public: tree() :root(nullptr),nil(nullptr) { nil = new treenode<T>(0); nil->color = black; root = nil;//确保每个叶子节点都是nil,哨兵节点 } ~tree() { deletenode(root); delete nil; } void push(T value) { insert(value); } void pop(T value) { remove( value); } void print() { _print(root); } }; template<typename T> void tree<T>::insert(T value) { treenode<T>* z = new treenode<T>(value); treenode<T>* y = nil; treenode<T>* x = root; while (x != nil) { y = x; if (z->data < x->data) x = x->left; else x = x->right; } z->parent = y; z->left = nil; z->right = nil; if (y == nil) root = z; else { if (z->data < y->data) { y->left = z; } else { y->right = z; } } exam(z); } template<typename T> void tree<T>::exam(treenode<T>* node) { while (node->parent->color== red) { if (node->parent == node->parent->parent->left)//父为祖父左的一种 { treenode<T>* p = node->parent->parent->right;//这个为叔 if (p->color == red) { node->parent->color = black; node->parent->parent->right->color = black; node->parent->parent->color = red; node = node->parent->parent; } else { if (node->data>node->parent->data)//左三角 { node = node->parent; RR(node); } //左直线 node->parent->parent->color = red; node->parent->color = black; LL(node->parent->parent); if (root->parent != nil) { root = node->parent; } } } else if( node->parent == node->parent->parent->right)//父为祖父右的一种 { treenode<T>* p = node->parent->parent->left;//这个为叔 if ( p->color == red) { node->parent->color = black; node->parent->parent->left->color = black; node->parent->parent->color = red; node = node->parent->parent; } else { if (node->data<node->parent->data)//右三角 { node = node->parent; LL(node); } //右直线 node->parent->color = black; node->parent->parent->color = red; RR(node->parent->parent); if (root->parent != nil) { root = node->parent; } } } } root->color = black; } template<typename T> void tree<T>::LL(treenode<T>* node) { treenode<T>* tem = node->left; treenode<T>* cur = node->left->right; if (node->parent == nil) { node->left->parent = nil; node->left->right = node; } else { if (node->data < node->parent->data) { node->parent->left = node->left; node->left->parent = node->parent;//改左子节点与父的关系 node->left->right = node;//改变旋转节点的位置 } else { node->parent->right = node->left; node->left->parent = node->parent;//改左子节点与父的关系 node->left->right = node;//改变旋转节点的位置 } } node->parent = tem; node->left = cur; cur->parent = node; } template<typename T> void tree<T>::RR(treenode<T>* node) { treenode<T>* tem = node->right; treenode<T>* cur = node->right->left; if (node->parent == nil) { node->right->parent = nil; node->right->left = node; } else { if (node->data < node->parent->data) { node->parent->left = node->right; node->right->parent = node->parent;//改右子节点与父的关系 node->right->left= node;//改变旋转节点的位置 } else { node->parent->right = node->right; node->right->parent = node->parent;//改右子节点与父的关系 node->right->left = node;//改变旋转节点的位置 } } node->parent = tem; node->right = cur; cur->parent = node; } template<typename T> void tree<T>::remove(T value) { treenode<T>* x = root; while (x != nil) { if (x->data < value) { x = x->right; } else if (x->data > value) { x = x->left; } else { if (x->left != nil && x->right != nil)//有两边 { treenode<T>* node = finmin(x->right); x->data = node->data;//用后继节点处理一下 delete_x(node);//删后继 } else { delete_x(x); } return; } } return; } template<typename T> void tree<T>::delete_x( treenode<T>*node) { if (node->left == nil && node->right == nil)//无孩子 { int color = node->color; if (color == red)//红色的 { node->parent->data < node->data ? node->parent->right = nil : node->parent->right = nil; delete node; } else//黑色的 { if (node == root) { root = nil; } else { exam2(node);//这里传的是要删除节点 node->parent->data < node->data ? node->parent->right = nil : node->parent->right = nil; delete node; } } } else if (node->left != nil)//有孩子 { if (node->parent->data > node->data) { node->left->parent = node->parent; node->parent->left = node->left; node->left->color = black; delete node; } else { node->left->parent = node->parent; node->parent->right = node->left; node->left->color = black; delete node; } } else { if (node->parent->data > node->data) { node->right->parent = node->parent; node->parent->left = node->right; node->right->color = black; delete node; } else { node->right->parent = node->parent; node->parent->right = node->right; node->right->color = black; delete node; } } } template<typename T> treenode<T>* tree<T>::finmin(treenode<T>* node) { treenode<T>* tem = node; while (tem->left != nil) { tem = tem->left; } return tem; } template<typename T> void tree<T>::rotateblack(treenode<T>* node,bool a)//传进来的是兄弟节点 { if (node->left->color == red ) { if (a == true){ node->left->color = node->parent->color; node->parent->color = black; RR(node); LL(node->parent->parent); } else { node->left->color = node->color; node->color = node->parent->color; node->parent->color = black; LL(node->parent); } } else if (node->right->color == red) { if (a == true) { node->right->color = node->color; node->color = node->parent->color; node->parent->color = black; RR(node->parent); } else { node->right->color = node->parent->color; node->parent->color = black; LL(node); RR(node->parent->parent); } } else { node->color = red; if (node->parent->color == red || node->parent == root) { node->parent->color = black; } else { exam2(node->parent); } } } template<typename T> void tree<T>::exam2(treenode<T>* node) { if (node->data < node->parent->data)//node是左节点,兄弟是右 { if (node->parent->right->color == red)//兄弟为红 { node->parent->right->color = black; node->parent->color = red; RR(node->parent);//朝要被删除的那个旋 exam2(node); } else { rotateblack(node->parent->right, true);//true是右,false是左 } } else//node是右节点,其兄弟是左 { if (node->parent->left->color == red) { node->parent->left->color = black; node->parent->color = red; LL(node->parent); exam2(node); } else { rotateblack(node->parent->left, false); } } }帮我把错的地方改对
最新发布
08-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值