PAT甲级 《树》专题练习(25/25)

35 篇文章 4 订阅
4 篇文章 0 订阅

1. 数叶子结点

题目链接:数叶子结点

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
const int M = N * N;
int h[N], e[M], ne[M], idx;
int cnt[N], height;
int n, m;
void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u, int depth)
{
	if (h[u] == -1)
	{
		height = max(height, depth);
		cnt[depth]++;
		return;
	}
	for (int i = h[u]; ~i; i = ne[i])
	{
		int j = e[i];
		dfs(j, depth + 1);
	}
}
int main()
{
	cin >> n >> m;
	memset(h, -1, sizeof h);
	for (int i = 0; i < m; i++)
	{
		int id, k;
		cin >> id >> k;
		for (int j = 0; j < k; j++)
		{
			int x;
			cin >> x;
			add(id, x);
		}
	}
	dfs(1, 1);
	for (int i = 1; i <= height; i++)
		cout << cnt[i] << ' ';
	return 0;
}

2. 树的遍历

题目链接:树的遍历

#include <bits/stdc++.h>
using namespace std;
const int N = 35;
int pos[N], in[N];
int n;
typedef struct node
{
	int data;
	node* left, * right;
}node, *tree;
tree create(int len, int* in, int *pos)
{
	if (len <= 0)return nullptr;
	tree T = (tree)malloc(sizeof(struct node));
	T->left = T->right = nullptr;
	T->data = pos[len - 1];
	int i = 0;
	for (i = 0; i < len; i++)
		if (T->data == in[i])
			break;
	T->left = create(i, in, pos);
	T->right = create(len - i - 1, in + i + 1, pos + i);
	return T;
}
void level_pos(tree T)
{
	queue<tree>q;
	q.push(T);
	while (q.size())
	{
		auto t = q.front();
		cout << t->data << ' ';
		q.pop();
		if (t->left)q.push(t->left);
		if (t->right)q.push(t->right);
	}
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)cin >> pos[i];
	for (int i = 0; i < n; i++)cin >> in[i];
	tree T = create(n, in, pos);
	level_pos(T);
	return 0;
}

3. 最深的根

题目链接:最深的根
并查集合并,并且求连通块的个数
递归求树的高度即可

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
const int M = N * N;
int h[N], e[M], ne[M], idx;
int n;
int height_max;
int f[N];
int res;
vector<int>ans;
void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int find(int x)
{
	if (x != f[x])f[x] = find(f[x]);
	return f[x];
}
int dfs(int u, int father)
{
	int depth = 0;
	for (int i = h[u]; ~i; i = ne[i])
	{
		int j = e[i];
		if (j == father)continue;
		depth = max(depth, dfs(j, u) + 1);
	}
	return depth;
}
int main()
{
	memset(h, -1, sizeof h);
	for (int i = 0; i < N; i++)f[i] = i;
	cin >> n;
	for (int i = 0; i < n - 1; i++)
	{
		int a, b;
		cin >> a >> b;
		if (find(a) != find(b))
			f[find(a)] = find(b);
		add(a, b), add(b, a);
	}
	for (int i = 1; i <= n; i++)
		if (f[i] == i)res++;
	if (res >= 2)
		printf("Error: %d components", res);
	else
	{
		for (int i = 1; i <= n; i++)
		{
			int height = dfs(i, -1);
			if (height > height_max)
			{
				height_max = height;
				ans.clear();
				ans.push_back(i);
			}
			else if (height == height_max)
				ans.push_back(i);
		}
	}
	for (auto x : ans)cout << x << endl;
	return 0;
}

4. 判断二叉搜索树

题目链接:判断二叉搜索树

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef struct node
{
	int data;
	node* left, * right;
}node, * tree;
int n;
vector<int>v1;
vector<int>v2;
vector<int>v3;
tree create(tree T, int x)
{
	if (!T)
	{
		T = (tree)malloc(sizeof(struct node));
		T->left = T->right = nullptr;//注意
		T->data = x;
	}
	else
	{
		if (x < T->data)
			T->left = create(T->left, x);
		else T->right = create(T->right, x);
	}
	return T;
}
tree create2(tree T, int x)
{
	if (!T)
	{
		T = (tree)malloc(sizeof(struct node));
		T->left = T->right = nullptr;
		T->data = x;
	}
	else
	{
		if (x < T->data)
			T->right = create2(T->right, x);
		else T->left = create2(T->left, x);
	}
	return T;
}
void pre(tree T)
{
	if (!T)return;
	v2.push_back(T->data);
	pre(T->left);
	pre(T->right);
}
void pre2(tree T)
{
	if (!T)return;
	v3.push_back(T->data);
	pre2(T->left);
	pre2(T->right);
}
void pos(tree T)
{
	if (!T)return;
	pos(T->left);
	pos(T->right);
	cout << T->data << ' ';
}
int main()
{
	cin >> n;
	tree T = nullptr;
	tree T2 = nullptr;
	for (int i = 0; i < n; i++)
	{
		int x;
		cin >> x;
		v1.push_back(x);
		T = create(T, x);
		T2 = create2(T2, x);
	}
	pre(T);
	pre2(T2);
	bool f = false;
	bool s = false;
	for (int i = 0; i < v1.size(); i++)
	{
		if (v1[i] != v2[i])
		{
			f = true;
			break;
		}
	}
	for (int i = 0; i < v1.size(); i++)
	{
		if (v1[i] != v3[i])
		{
			s = true;
			break;
		}
	}
	if (!f && s)
	{
		puts("YES");
		pos(T);
	}
	else if (f && !s)
	{
		puts("YES");
		pos(T2);
	}
	else if (!f && !s)
	{
		puts("YES");
		pos(T);
	}
	else puts("NO");
	return 0;
}

5. 完全二叉搜索树

题目链接:完全二叉搜索树
完全二叉树,所以可以用数组来存:
该结点为 u ,左孩子为 2 * u ,右孩子为 2 * u + 1
则这个数组1~n是全部填满的
二叉搜索树的中序遍历是从小到大的排序,所以先进行sort就是这棵树的中序遍历,再根据中序遍历存这棵树,将res数组枚举就是层序遍历

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n;
int in[N];
int res[N];
int cnt = 0;
void dfs(int u)
{
	if (u * 2 <= n)dfs(u * 2);
	res[u] = in[cnt++];
	if (u * 2 + 1 <= n)dfs(u * 2 + 1);
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)cin >> in[i];
	sort(in, in + n);
	dfs(1);
	for (int i = 1; i <= n; i++)cout << res[i] << ' ';
	return 0;
}

6. 再次树遍历

题目链接 :再次树遍历
对于每一个push操作可以看成先序遍历,pop可以看作先序遍历
根据两种遍历还原树并求出后续遍历

#include <bits/stdc++.h>
using namespace std;
const int N = 35;
int a[N], b[N];
int c[N];
int n;
string op;
int x;
int cnt1, cnt2;
int k = 0;
vector<int>v;
typedef struct node
{
	int data;
	node* left, * right;
}node, * tree;
tree create(int len, int* c, int* b)
{
	if (len <= 0)return nullptr;
	tree T = (tree)malloc(sizeof(struct node));
	T->left = T->right = nullptr;
	T->data = c[0];
	int i = 0;
	for (i = 0; i < len; i++)
		if (T->data == b[i])
			break;
	T->left = create(i, c + 1, b);
	T->right = create(len - i - 1, c + i + 1, b + i + 1);
	return T;
}
void pos(tree T)
{
	if (!T)return;
	pos(T->left);
	pos(T->right);
	v.push_back(T->data);
}
int main()
{
	cin >> n;
	while (cin >> op)
	{
		if (op == "Push")
		{
			cin >> x;
			a[cnt1++] = x;
			c[k++] = x;
		}
		else
			b[cnt2++] = a[--cnt1];
	}
	tree T = nullptr;
	T = create(k, c, b);
	pos(T);
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i];
		if (i < v.size() - 1)cout << ' ';
	}
	return 0;
}

7. 构建二叉搜索树

题目链接:构建二叉搜索树
二叉搜索树,中序遍历是从小到大的排序,先将其进行排序,根据其输入再用中序遍历将其还原,最后进行层序遍历

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int n;
struct node
{
	int l, r;
	int data;
}tr[N];
vector<int>v;
int cnt;
void dfs(int u)
{
	if (u == -1)return;
	if (~tr[u].l)dfs(tr[u].l);
	tr[u].data = v[cnt++];
	if (~tr[u].r)dfs(tr[u].r);
}
void bfs(int u)
{
	queue<int>q;
	q.push(u);
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		cout << tr[t].data << ' ';
		if (~tr[t].l)q.push(tr[t].l);
		if (~tr[t].r)q.push(tr[t].r);
	}
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> tr[i].l >> tr[i].r;
	v.resize(n);
	for (auto& x : v)cin >> x;
	sort(v.begin(), v.end());
	dfs(0);
	bfs(0);
	return 0;
}

8. 反转二叉树

题目链接:反转二叉树
反向建树,哈希标记找根节点,中序和层序遍历输出

#include <bits/stdc++.h>
using namespace std;
const int N = 15;
struct node
{
	int data;
	int l, r;
}tr[N];
int n;
unordered_map<int, bool>mp;
void dfs(int u)
{
	if (~tr[u].l)dfs(tr[u].l);
	cout << tr[u].data << ' ';
	if (~tr[u].r)dfs(tr[u].r);
}
void bfs(int u)
{
	queue<int>q;
	q.push(u);
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		cout << tr[t].data << ' ';
		if (~tr[t].l)q.push(tr[t].l);
		if (~tr[t].r)q.push(tr[t].r);
	}
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		char a, b;
		cin >> a >> b;
		if (b != '-')
		{
			mp[b - '0'] = true;
			tr[i].l = b - '0';
		}
		else tr[i].l = -1;
		if (a != '-')
		{
			mp[a - '0'] = true;
			tr[i].r = a - '0';
		}
		else tr[i].r = -1;
		tr[i].data = i;
	}
	int root = -1;
	for (int i = 0; i < n; i++)
	{
		if (!mp.count(i))
		{
			root = i;
			break;
		}
	}
	bfs(root);
	cout << endl;
	dfs(root);
	return 0;
}

9. 完全二叉树

看到完全二叉树自然想到2 * u, 2 * u+1
这样可以判断其是否是一个完全二叉树。

#include <bits/stdc++.h>
using namespace std;
const int N = 55;
struct node
{
	int l, r;
	int data;
}tr[N];
unordered_map<int, bool>mp;
int n;
int maxv;
int ud;
void dfs(int u, int k)
{
    if(u==-1)return;
	if (k > maxv)
	{
		maxv = k;
		ud = u;
	}
	dfs(tr[u].l, 2 * k);
	dfs(tr[u].r, 2 * k + 1);
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		string a, b;
		cin >> a >> b;
		if (a != "-")
		{
			int t = 0;
			for (int i = 0; i < a.size(); i++)
				t = t * 10 + a[i] - '0';
			tr[i].l = t;
			mp[t] = true;
		}
		else tr[i].l = -1;
		if (b != "-")
		{
			int t = 0;
			for (int i = 0; i < b.size(); i++)
				t = t * 10 + b[i] - '0';
			tr[i].r = t;
			mp[t] = true;
		}
		else tr[i].r = -1;
		tr[i].data = i;
	}
	int root = -1;
	for (int i = 0; i < n; i++)
		if (!mp.count(i))
		{
			root = i;
			break;
		}
	dfs(root, 1);
	if (maxv == n)cout << "YES " << ud << endl;
	else cout << "NO " << root << endl;
	return 0;
}

10. 二叉树最后两层结点的个数

题目链接:二叉树最后两层结点的个数
求树的深度的同时保存当前深度的结点个数

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef struct node
{
	int data;
	node* left, * right;
}node, * tree;
int n;
int cnt[N];
int h;
tree create(tree T, int x)
{
	if (!T)
	{
		T = (tree)malloc(sizeof(struct node));
		T->left = T->right = nullptr;
		T->data = x;
	}
	else
	{
		if (x <= T->data)T->left = create(T->left, x);
		else T->right = create(T->right, x);
	}
	return T;
}
void dfs(tree T, int depth)
{
	if (!T)return;
	cnt[depth]++;
	h = max(h, depth);
	if (T->left)dfs(T->left, depth + 1);
	if (T->right)dfs(T->right, depth + 1);
}
int main()
{
	cin >> n;
	tree T = nullptr;
	for (int i = 0; i < n; i++)
	{
		int x;
		cin >> x;
		T = create(T, x);
	}
	dfs(T, 1);
	printf("%d + %d = %d", cnt[h], cnt[h - 1], cnt[h - 1] + cnt[h]);
	return 0;
}

11. 前序遍历和后续遍历

题目链接:前序遍历和后序遍历
前序遍历和后序遍历无法确定一个二叉树,这题通过枚举左子树右子树的长度,判断这棵树是否合法,并将中序遍历存在字符串中

#include <bits/stdc++.h>
using namespace std;
const int N = 40;
int n;
int pre[N], pos[N];
int dfs(int len, int *pre, int *pos, string& in)
{
	if (len <= 0)return 1;//空树成立
	if (pre[0] != pos[len - 1])return 0;//根节点不同,不合法
	int cnt = 0;
	for (int i = 0; i < len; i++)
	{
		string lin, rin;
		int lcnt = dfs(i, pre + 1, pos, lin);
		int rcnt = dfs(len - i - 1, pre + 1 + i, pos + i, rin);
		cnt += lcnt * rcnt;
		if (lcnt && rcnt)//左右子树都合法,这个树才合法
			in = lin + to_string(pre[0]) + ' ' + rin;
		if (cnt > 1)break;//题目要求只求一个
	}
	return cnt;
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)cin >> pre[i];
	for (int i = 0; i < n; i++)cin >> pos[i];
	string in;
	int cnt = dfs(n, pre, pos, in);
	if (cnt > 1)puts("No");
	else puts("Yes");
	in.pop_back();
	cout << in << endl;
	return 0;
}

12. Z 字形遍历二叉树

题目链接:Z字形遍历二叉树
队列中的点为当前层的结点

#include <bits/stdc++.h>
using namespace std;
const int N = 35;
typedef struct node
{
	int data;
	node* left, * right;
}node, * tree;
int n;
int in[N], pos[N];
vector<int>v, res;
tree create(int len, int* in, int* pos)
{
	if (len <= 0)return nullptr;
	tree T = new node;
	T->left = T->right = nullptr;
	T->data = pos[len - 1];
	int i = 0;
	for (i = 0; i < len; i++)
		if (T->data == in[i])
			break;
	T->left = create(i, in, pos);
	T->right = create(len - i - 1, in + i + 1, pos + i);
	return T;
}
void bfs(tree T)
{
	queue<tree>q;
	q.push(T);
	int f=1;
	while (q.size())
	{
	    int s=q.size();
		while (s--)
		{
			auto t = q.front();
			q.pop();
			v.push_back(t->data);
			if(t->left)q.push(t->left);
			if(t->right)q.push(t->right);
		}
		if (~f)reverse(v.begin(), v.end());
		for (auto x : v)res.push_back(x);
		f *= -1;
		v.clear();
	}
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)cin >> in[i];
	for (int i = 0; i < n; i++)cin >> pos[i];
	tree T = nullptr;
	T = create(n, in, pos);
	bfs(T);
	for (auto x : res)cout << x << ' ';
	return 0;
}

13. 后序遍历

题目链接:后序遍历建树
通过前序遍历和中序遍历建树,回溯时第一个数字即为后序遍历的第一个数字

#include <bits/stdc++.h>
using namespace std;
const int N=50010;
typedef struct node
{
    int data;
    node *left,*right;
}node,*tree;
int pre[N], in[N];
int n;
vector<int>v;
tree create(int len,int *pre,int *in)
{
    if(len<=0)return nullptr;
    tree T=new node;
    T->left=T->right=nullptr;
    T->data=pre[0];
    int i=0;
    for(i=0;i<len;i++)
    if(T->data==in[i])
    break;
    T->left=create(i,pre+1,in);
    T->right=create(len-i-1,pre+1+i,in+1+i);
    v.push_back(T->data);
    if(v.size()==1)
    {
        cout<<v[0];
        exit(0);
    }
    return T;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)cin>>pre[i];
    for(int i=0;i<n;i++)cin>>in[i];
    tree T=nullptr;
    T=create(n,pre,in);
    return 0;
}

14. AVL树的根

题目链接:AVL树的根
记得每次要更新高度

#include <bits/stdc++.h>
using namespace std;
typedef struct node
{
	int data;
	node* left, * right;
	int hight;
}node, * tree;
int n;
int get_hight(tree T)
{
	if (!T)return 0;
	else return T->hight;
}
tree L(tree T)//左单旋
{
	tree B = T->left;
	T->left = B->right;
	B->right = T;
	T->hight = max(get_hight(T->left), get_hight(T->right)) + 1;
	B->hight = max(get_hight(B->left), get_hight(T)) + 1;
	return B;
}
tree R(tree T)//右单旋
{
	tree B = T->right;
	T->right = B->left;
	B->left = T;
	T->hight = max(get_hight(T->left), get_hight(T->right)) + 1;
	B->hight = max(get_hight(B->right), get_hight(T)) + 1;
	return B;
}
tree LR(tree T)
{
	T->left = R(T->left);
	return L(T);
}
tree RL(tree T)
{
	T->right = L(T->right);
	return R(T);
}
tree create(tree T, int x)
{
	if (!T)
	{
		T = (tree)malloc(sizeof(struct node));
		T->right = T->right = nullptr;
		T->hight = 0;
		T->data = x;
	}
	else if (x < T->data)
	{
		T->left = create(T->left, x);
		if (get_hight(T->left) - get_hight(T->right) == 2)//回溯找最小失衡树
			if (x < T->left->data)
				T = L(T);
			else T = LR(T);
	}
	else if (x > T->data)
	{
		T->right = create(T->right, x);
		if (get_hight(T->left) - get_hight(T->right) == -2)
			if (x > T->right->data)
				T = R(T);
			else T = RL(T);
	}
	T->hight = max(get_hight(T->left), get_hight(T->right)) + 1;
	return T;
}
int main()
{
	cin >> n;
	tree T = nullptr;
	for (int i = 0; i < n; i++)
	{
		int x;
		cin >> x;
		T = create(T, x);
	}
	cout << T->data << endl;
	return 0;
}

15. 判断完全AVL树

题目链接:判断完全AVL树
判断是否为完全二叉树
如果该节点没有孩子,其层序遍历的之后的结点存在,且有孩子,则不是完全二叉树。或某结点没有左孩子只有有孩子也不是完全二叉树。

#include <bits/stdc++.h>
using namespace std;
typedef struct node
{
	int data;
	int height;
	node* left, * right;
}node, * tree;
bool f = false;
int n;
int get_height(tree T)
{
	if (!T)return 0;
	return T->height;
}
void updateHeight(tree& T)
{
	T->height = max(get_height(T->left), get_height(T->right)) + 1;
}
int getFactor(tree T)
{
	return get_height(T->left) - get_height(T->right);
}
void L(tree& T)
{
	tree B = T->right;
	T->right = B->left;
	B->left = T;
	updateHeight(T);
	updateHeight(B);
	T = B;
}
void R(tree& T)
{
	tree B = T->left;
	T->left = B->right;
	B->right = T;
	updateHeight(T);
	updateHeight(B);
	T = B;
}
tree create(tree T, int x)
{
	if (!T)
	{
		T = (tree)malloc(sizeof(struct node));
		T->left = T->right = nullptr;
		T->data = x;
		T->height = 1;
	}
	else
	{
		if (x < T->data)
		{
			T->left = create(T->left, x);
			updateHeight(T);
			if (getFactor(T) == 2)
			{
				if (getFactor(T->left) == 1)
					R(T);
				else if (getFactor(T->left) == -1)
				{
					L(T->left);
					R(T);
				}
			}
		}
		else
		{
			T->right = create(T->right, x);
			updateHeight(T);
			if (getFactor(T) == -2)
			{
				if (getFactor(T->right) == -1)
					L(T);
				else if (getFactor(T->right) == 1)
				{
					R(T->right);
					L(T);
				}
			}
		}
	}
	return T;
}
void bfs(tree T)
{
	queue<tree>q;
	q.push(T);
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		cout << t->data << ' ';
		if (t->left == nullptr || t->right == nullptr)
			if (q.front() && (q.front()->left || q.front()->right))f = true;
		if (t->left == nullptr && t->right)f = true;
		if (t->left)q.push(t->left);
		if (t->right)q.push(t->right);
	}
}
int main()
{
	cin >> n;
	tree T = nullptr;
	for (int i = 0, x; i < n, cin >> x; i++)
		T = create(T, x);
	bfs(T);
	cout << endl;
	if (f)puts("NO");
	else puts("YES");
	return 0;
}

16. 判断红黑树

题目链接:判断红黑树

#include <bits/stdc++.h>
using namespace std;
vector<int>pre;
typedef struct node
{
	int data;
	node* left, * right;
}node, * tree;
int _, n;
tree create(tree T, int x)
{
	if (!T)
	{
		T = (tree)malloc(sizeof(struct node));
		T->left = T->right = nullptr;
		T->data = x;
	}
	else
	{
		if (abs(x) < abs(T->data))
			T->left = create(T->left, x);
		else T->right = create(T->right, x);
	}
	return T;
}
bool check(tree T)//判断红色节点的左右子结点是否是黑色
{
	if (!T)return true;
	if (T->data < 0)
	{
		if (T->left && T->left->data < 0)return false;
		if (T->right && T->right->data < 0)return false;
	}
	return check(T->left) && check(T->right);
}
//当前结点到叶子结点路径上的黑色结点的个数,准确来说是到叶子结点的各个路径上
//黑色结点数量的最大值,如果满足红黑树,自然是各个路径相等,反之不是
int get_num(tree T)
{
	if (!T)return 0;
	int l = get_num(T->left);
	int r = get_num(T->right);
	if (T->data > 0)return max(l, r) + 1;
	else return max(l, r);
}
bool check2(tree T)//判断当前结点到根结点各个路径上黑色结点个数是否相等
{
	if (!T)return true;
	int l = get_num(T->left);
	int r = get_num(T->right);
	if (l != r)return false;
	return check2(T->left) && check2(T->right);
}
void solve()
{
	cin >> n;
	pre.resize(n);
	tree T = nullptr;
	for (int i = 0; i < n; i++)
	{
		cin >> pre[i];
		T = create(T, pre[i]);
	}
	if (T->data < 0 || !check(T) || !check2(T))puts("No");
	else puts("Yes");
}
int main()
{
	cin >> _;
	while (_--)solve();
}

17. 等重路径

题目链接:等重路径
在叶子层时判断是否等重,是则保留结果

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int g[N][N];
int n, m, S;
vector<vector<int>>ans;
vector<int>path;
int w[N];
void dfs(int u, int s, vector<int>& path)
{
	bool is_leaf = true;
	for (int i = 0; i < n; i++)
		if (g[u][i])
		{
			is_leaf = false;
			break;
		}
	if (is_leaf)
	{
		if (s == S)
			ans.push_back(path);
	}
	else if (!is_leaf)
	{
		for (int i = 0; i < n; i++)
		{
			if (g[u][i])
			{
				path.push_back(w[i]);
				dfs(i, s + w[i], path);
				path.pop_back();//并不是还原现场,只是清除数组
			}
		}
	}
}
int main()
{
	cin >> n >> m >> S;
	for (int i = 0; i < n; i++)cin >> w[i];
	path.push_back(w[0]);
	for (int i = 0; i < m; i++)
	{
		int id, k;
		cin >> id >> k;
		for (int j = 0; j < k; j++)
		{
			int x;
			cin >> x;
			g[id][x] = 1;
		}
	}
	dfs(0, w[0], path);
	sort(ans.begin(), ans.end(), greater<vector<int>>());
	for (auto x : ans)
	{
		for (int i = 0; i < x.size(); i++)cout << x[i] << ' ';
		cout << endl;
	}
	return 0;
}

18. 最大的一代

题目链接:最大的一代
层序遍历求该层最多结点并保存
也可以深搜记录每个深度的结点数
bfs

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int g[N][N];
int n, m;
vector<int>res;
int cnt;
int cnt_r;
void bfs()
{
    queue<int>q;
    q.push(1);
    while (q.size())
    {
        int s = q.size();
        vector<int>v;
        while (s--)
        {
            auto t = q.front();
            q.pop();
            v.push_back(t);
            for (int i = 1; i <= n; i++)
                if (g[t][i])q.push(i);
        }
        cnt++;
        if (v.size() > res.size())
        {
            res.clear();
            for (auto x : v)res.push_back(x);
            cnt_r = cnt;
        }
    }
}
int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int id, k;
        cin >> id >> k;
        for (int j = 0; j < k; j++)
        {
            int x;
            cin >> x;
            g[id][x] = 1;
        }
    }
    bfs();
    cout << res.size() << ' ' << cnt_r;
    return 0;
}

dfs

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int g[N][N];
int n, m;
int cnt[N];
int maxv;
void dfs(int u, int depth)
{
	cnt[depth]++;
	maxv = max(maxv, depth);
	for (int i = 1; i <= n; i++)
		if (g[u][i])
			dfs(i, depth + 1);
}
int main()
{
	cin >> n >> m;
	for (int i = 0; i < m; i++)
	{
		int id, k;
		cin >> id >> k;
		for (int j = 0; j < k; j++)
		{
			int x;
			cin >> x;
			g[id][x] = 1;
		}
	}
	dfs(1, 1);
	int res = 0;
	int d = 0;
	for (int i = 1; i <= maxv; i++)
	{
		if (cnt[i] > res)
		{
			res = cnt[i];
			d = i;
		}
	}
	cout << res << ' ' << d << endl;
	return 0;
}

19. 供应链总销售额

题目链接:供应链总销售额
深搜,在叶子结点处计算销售额

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int>v[N];
int n;
double p;
double r;
double w[N];
double sum;
void dfs(int u, int depth)
{
	bool is_leaf = true;
	for (int i = 0; i < v[u].size(); i++)
		if (v[u][i])
		{
			is_leaf = false;
			break;
		}
	if (is_leaf)sum += w[u] * p * pow(1 + r, depth);
	else
		for (int i = 0; i < v[u].size(); i++)
			if (v[u][i])dfs(v[u][i], depth + 1);
}
int main()
{
	cin >> n >> p >> r;
	r /= 100;
	for (int i = 0; i < n; i++)
	{
		int k;
		cin >> k;
		for (int j = 0; j < k; j++)
		{
			int x;
			cin >> x;
			v[i].push_back(x);
		}
		if (!k)
		{
			int x;
			cin >> x;
			w[i] = x;
		}
	}
	dfs(0, 0);
	printf("%.1f", sum);
	return 0;
}

20. 供应链的最高价格

题目链接:供应链的最高价格
记忆化搜索

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
double P, R;
int n;
int p[N], f[N];
int dfs(int u)
{
	if (~f[u])return f[u];
	if (p[u] == -1)return f[u] = 0;
	return f[u] = dfs(p[u]) + 1;
}
int main()
{
	cin >> n >> P >> R;
	for (int i = 0; i < n; i++)cin >> p[i];
	memset(f, -1, sizeof f);
	int res = 0, cnt = 0;
	for (int i = 0; i < n; i++)
	{
		if (dfs(i) > res)
		{
			res = dfs(i);
			cnt = 1;
		}
		else if (dfs(i) == res)cnt++;
	}
	printf("%.2f %d\n", P * pow(1 + R / 100, res), cnt);
	return 0;
}

21. 供应商的最低价格

题目链接:供应商的最低价格
深搜,求每层结点数量

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int>v[N];
int w[N];
int n;
double P, R;
int cnt[N];
void dfs(int u, int depth)
{
	bool is_leaf = true;
	if (v[u].size())is_leaf = false;
	if (is_leaf)cnt[depth]++;
	else
	{
		for (int i = 0; i < v[u].size(); i++)
			dfs(v[u][i], depth + 1);
	}
}
int main()
{
	cin >> n >> P >> R;
	R /= 100;
	for (int i = 0; i < n; i++)
	{
		int k;
		cin >> k;
		for (int j = 0; j < k; j++)
		{
			int x;
			cin >> x;
			v[i].push_back(x);
		}
	}
	dfs(0, 0);
	int minv = 0x3f3f3f3f;
	for (int i = 0; i < n; i++)
	{
		if (cnt[i] != 0)
		{
			minv = i;
			break;
		}
	}
	printf("%.4f %d", P * pow(1 + R, minv), cnt[minv]);
	return 0;
}

22. 中缀表达式

题目链接: 中缀表达式
如果该节点不是根节点 则在该返回值的左右两边加上括号

#include<bits/stdc++.h>
using namespace std;
const int N = 25;
int n;
struct node
{
	int l, r;
	string data;
}tr[N];
unordered_map<int, bool>mp;
bool is_leaf[N];
string dfs(int u)
{
	string left, right;
	if (~tr[u].l)
	{
		left = dfs(tr[u].l);
		if (!is_leaf[tr[u].l])left = "(" + left + ")";
	}
	if (~tr[u].r)
	{
		right = dfs(tr[u].r);
		if (!is_leaf[tr[u].r])right = "(" + right + ")";
	}
	return left + tr[u].data + right;
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> tr[i].data >> tr[i].l >> tr[i].r;
		if (~tr[i].l)mp[tr[i].l] = true;
		if (~tr[i].r)mp[tr[i].r] = true;
		if (tr[i].r == -1 && tr[i].l == -1)is_leaf[i] = true;
	}
	int root = -1;
	for(int i=1;i<=n;i++)
		if (!mp[i])
		{
			root = i;
			break;
		}
	cout << dfs(root) << endl;
	return 0;
}

23. 堆路径

题目链接:堆路径

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n;
int v[N];
vector<int>path;
bool is_great = true, is_min = true;
void dfs(int u)
{
	//if (u > n)return;
	path.push_back(v[u]);
	if (u * 2 > n)
	{
		cout << path[0] << ' ';
		for (int i = 1; i < path.size(); i++)
		{
			cout << path[i] << ' ';
			if (path[i - 1] > path[i])is_min = false;
			if (path[i - 1] < path[i])is_great = false;
		}
		cout << endl;
	}
	if (u * 2 + 1 <= n)dfs(u * 2 + 1);
	if (u * 2 <= n)dfs(u * 2);
	path.pop_back();
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> v[i];
	dfs(1);
	if (is_great)puts("Max Heap");
	else if (is_min)puts("Min Heap");
	else puts("Not Heap");
	return 0;
}

24. 最近公共祖先

最近公共祖先
二叉搜索树特性: 父节点 > 左儿子,父节点 <= 右儿子
前序遍历特性:根->左->右的顺序遍历
从前序遍历中找到第一个符合二叉搜索树特性的结点为x,y的共同父节点
建立哈希表,检查当前节点是否是该树的结点

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int n, m;
int pre[N];
unordered_map<int, bool>mp;
int main()
{
	cin >> m >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> pre[i];
		mp[pre[i]] = true;
	}
	for (int i = 0; i < m; i++)
	{
		int x, y;
		cin >> x >> y;
		if (mp[x] && mp[y])
		{
			int fa;
			for (int j = 0; j < n; j++)
			{
				if (pre[j] >= x && pre[j] <= y || pre[j] >= y && pre[j] <= x)
				{
					fa = pre[j];
					break;
				}
			}
			if (x == fa || y == fa)    printf("%d is an ancestor of %d.\n", fa, fa != x ? x : y);
			else printf("LCA of %d and %d is %d.\n", x, y, fa);
		}
		else
		{
			if(!mp[x]&&!mp[y])printf("ERROR: %d and %d are not found.\n", x, y);
			else if(!mp[x])printf("ERROR: %d is not found.\n", x);
			else if(!mp[y])printf("ERROR: %d is not found.\n", y);
		}
	}
	return 0;
}

25. 二叉树的最近公共祖先

题目链接:二叉树的最近公共最先

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int n, m;
int pre[N], in[N];
unordered_set<int>S;
unordered_map<int, int>mp;
typedef struct node
{
	int data;
	node* left, * right;
}node, * tree;
tree create(int len, int* pre, int* in)
{
	if (len <= 0)return nullptr;
	tree T = (tree)malloc(sizeof(struct node));
	T->left = T->right = nullptr;
	T->data = pre[0];
	int i = 0;
	for (i = 0; i < len; i++)
		if (T->data == in[i])
			break;
	T->left = create(i, pre + 1, in);
	T->right = create(len - i - 1, pre + i + 1, in + i + 1);
	return T;
}
tree find(tree T, int x, int y)
{
	if (!T || T->data == x || T->data == y)return T;
	tree l = find(T->left, x, y);
	tree r = find(T->right, x, y);
	return l && r ? T : l ? l : r;
}
int main()
{
	cin >> m >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> in[i];
		mp[in[i]] = i;
	}
	for (int i = 0; i < n; i++)cin >> pre[i];
	for (int i = 0; i < n; i++)S.insert(pre[i]);
	tree T = create(n, pre, in);
	while (m--)
	{
		int x, y;
		cin >> x >> y;
		if (!S.count(x) || !S.count(y))
		{
			if (!S.count(x) && !S.count(y))printf("ERROR: %d and %d are not found.\n", x, y);
			else if (!S.count(x))printf("ERROR: %d is not found.\n", x);
			else printf("ERROR: %d is not found.\n", y);
			continue;
		}

		tree lca = find(T, x, y);
		if (lca->data != x && lca->data != y)printf("LCA of %d and %d is %d.\n", x, y, lca->data);
		else if (lca->data == x)printf("%d is an ancestor of %d.\n", x, y);
		else printf("%d is an ancestor of %d.\n", y, x);

	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leimingzeOuO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值