题目## 题目
解题思路
-
基本思路:
- 使用递归方法遍历二叉树,检查每个节点是否满足二分查找树的性质。
- 对于每个节点,确保其左子树的所有节点值小于该节点值,右子树的所有节点值大于该节点值。
-
实现方法:
- 解析输入构建二叉树。
- 使用辅助函数进行递归检查,传递当前节点的值范围。
代码
#include <iostream>
#include <unordered_map>
#include <sstream>
#include <limits>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
bool isBST(TreeNode* node, int minVal, int maxVal) {
if (!node) return true;
if (node->val <= minVal || node->val >= maxVal) return false;
return isBST(node->left, minVal, node->val) && isBST(node->right, node->val, maxVal);
}
int main() {
int rootVal;
cin >> rootVal;
unordered_map<int, TreeNode*> nodes;
TreeNode* root = new TreeNode(rootVal);
nodes[rootVal] = root;
string line;
cin.ignore(); // 忽略换行符
while (getline(cin, line)) {
int parentVal, leftVal, rightVal;
char colon, pipe;
stringstream ss(line);
ss >> parentVal >> colon >> leftVal >> pipe >> rightVal;
if (nodes.find(parentVal) == nodes.end()) {
nodes[parentVal] = new TreeNode(parentVal);
}
TreeNode* parent = nodes[parentVal];
if (leftVal != -1) {
parent->left = new TreeNode(leftVal);
nodes[leftVal] = parent->left;
}
if (rightVal != -1) {
parent->right = new TreeNode(rightVal);
nodes[rightVal] = parent->right;
}
}
// 检查是否为二分查找树
if (isBST(root, numeric_limits<int>::min(), numeric_limits<int>::max())) {
cout << 1 << endl; // 是二分查找树
} else {
cout << 0 << endl; // 不是二分查找树
}
return 0;
}
import java.util.*;
public class Main {
static class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) {
val = x;
}
}
static boolean isBST(TreeNode node, int minVal, int maxVal) {
if (node == null) return true;
if (node.val <= minVal || node.val >= maxVal) return false;
return isBST(node.left, minVal, node.val) && isBST(node.right, node.val, maxVal);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int rootVal = sc.nextInt();
sc.nextLine(); // 读取换行符
Map<Integer, TreeNode> nodes = new HashMap<>();
TreeNode root = new TreeNode(rootVal);
nodes.put(rootVal, root);
while (sc.hasNextLine()) {
String line = sc.nextLine();
String[] parts = line.split(":|\\|");
int parentVal = Integer.parseInt(parts[0]);
int leftVal = Integer.parseInt(parts[1]);
int rightVal = Integer.parseInt(parts[2]);
if (!nodes.containsKey(parentVal)) {
nodes.put(parentVal, new TreeNode(parentVal));
}
TreeNode parent = nodes.get(parentVal);
if (leftVal != -1) {
parent.left = new TreeNode(leftVal);
nodes.put(leftVal, parent.left);
}
if (rightVal != -1) {
parent.right = new TreeNode(rightVal);
nodes.put(rightVal, parent.right);
}
}
// 检查是否为二分查找树
if (isBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE)) {
System.out.println(1); // 是二分查找树
} else {
System.out.println(0); // 不是二分查找树
}
}
}
import sys
sys.setrecursionlimit(100000) # 扩大递归栈深度
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def is_bst(node, min_val, max_val):
if not node:
return True
if node.val <= min_val or node.val >= max_val:
return False
return is_bst(node.left, min_val, node.val) and is_bst(node.right, node.val, max_val)
def main():
root_val = int(input())
nodes = {}
root = TreeNode(root_val)
nodes[root_val] = root
try:
while True:
line = input().strip()
if not line:
break
# 解析输入行
parts = line.split(':')
parent_val = int(parts[0])
left_val, right_val = map(int, parts[1].split('|'))
# 如果父节点不存在,创建父节点
if parent_val not in nodes:
nodes[parent_val] = TreeNode(parent_val)
parent = nodes[parent_val]
# 创建左右子节点
if left_val != -1:
parent.left = TreeNode(left_val)
nodes[left_val] = parent.left
if right_val != -1:
parent.right = TreeNode(right_val)
nodes[right_val] = parent.right
except EOFError:
pass
# 检查是否为二分查找树
if is_bst(root, float('-inf'), float('inf')):
print(1) # 是二分查找树
else:
print(0) # 不是二分查找树
if __name__ == "__main__":
main()
算法及复杂度
- 算法:二叉树遍历
- 时间复杂度: O ( n ) \mathcal{O(n)} O(n),其中 n n n 为节点数量
- 空间复杂度: O ( n ) \mathcal{O(n)} O(n),用于存储树的节点
解题思路
这是一道树形结构的路径选择问题,主要约束条件如下:
- 每条道路要么全部布置花灯,要么完全不布置
- 至少要有一条通向首都的路径布置花灯
- 每个城市最多选择两条相连道路布置花灯
- 所有布置花灯的道路必须构成连通子图
- 总路径长度不能超过给定上限 m m m
代码
#include <bits/stdc++.h>
using namespace std;
using Array = vector<int>;
set<int> dfs(int root, vector<Array>& sons, Array& d, int m) {
if (sons[root].size() == 0)
return set<int>({0});
vector<set<int>> sts;
for (auto it = sons[root].begin(); it != sons[root].end(); ++it) {
sts.push_back(dfs(*it, sons, d, m));
}
set<int> ret({0});
// 选择单条路径
for (auto it = sts.begin(); it != sts.end(); ++it)
for (auto it2 = it->begin(); it2 != it->end(); ++it2)
if (d[sons[root][it - sts.begin()]] + *it2 <= m)
ret.insert(d[sons[root][it - sts.begin()]] + *it2);
// 选择两条路径
for (auto it_i = sts.begin(); next(it_i) != sts.end(); ++it_i) {
for (auto it_j = it_i + 1; it_j != sts.end(); ++it_j) {
for (auto it = it_i->begin(); it != it_i->end(); ++it) {
for (auto it2 = it_j->begin(); it2 != it_j->end(); ++it2) {
if (d[sons[root][it_i - sts.begin()]] + d[sons[root][it_j - sts.begin()]] + *it + *it2 <= m)
ret.insert(d[sons[root][it_i - sts.begin()]] + d[sons[root][it_j - sts.begin()]] + *it + *it2);
}
}
}
}
return ret;
}
int main() {
int m, n;
while (cin >> m >> n) {
vector<Array> sons(n);
Array father(n, -1), d(n, 0);
for (int i = 0, u, v, dd; i < n - 1; i++) {
cin >> u >> v >> dd;
d[v] = dd;
sons[u].push_back(v);
father[v] = u;
}
int root = 0;
for (; root < father.size() && father[root] != -1; ++root) {}
set<int> st = dfs(root, sons, d, m);
cout << (st.empty() ? 0 : *st.rbegin()) << endl;
}
return 0;
}
import java.util.*;
public class Main {
static class Node {
List<Integer> sons = new ArrayList<>();
}
static TreeSet<Integer> dfs(int root, Node[] nodes, int[] dist, int m) {
if (nodes[root].sons.isEmpty()) {
return new TreeSet<>(Arrays.asList(0));
}
List<TreeSet<Integer>> childPaths = new ArrayList<>();
for (int son : nodes[root].sons) {
childPaths.add(dfs(son, nodes, dist, m));
}
TreeSet<Integer> result = new TreeSet<>();
result.add(0);
// 选择单条路径
for (int i = 0; i < childPaths.size(); i++) {
for (int len : childPaths.get(i)) {
if (dist[nodes[root].sons.get(i)] + len <= m) {
result.add(dist[nodes[root].sons.get(i)] + len);
}
}
}
// 选择两条路径
for (int i = 0; i < childPaths.size() - 1; i++) {
for (int j = i + 1; j < childPaths.size(); j++) {
for (int len1 : childPaths.get(i)) {
for (int len2 : childPaths.get(j)) {
int total = dist[nodes[root].sons.get(i)] +
dist[nodes[root].sons.get(j)] + len1 + len2;
if (total <= m) result.add(total);
}
}
}
}
return result;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int m = sc.nextInt();
int n = sc.nextInt();
Node[] nodes = new Node[n];
int[] father = new int[n];
int[] dist = new int[n];
Arrays.fill(father, -1);
for (int i = 0; i < n; i++) nodes[i] = new Node();
for (int i = 0; i < n - 1; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
int d = sc.nextInt();
nodes[u].sons.add(v);
father[v] = u;
dist[v] = d;
}
int root = 0;
while (root < n && father[root] != -1) root++;
TreeSet<Integer> paths = dfs(root, nodes, dist, m);
System.out.println(paths.isEmpty() ? 0 : paths.last());
}
}
}
from collections import defaultdict
def dfs(root, sons, dist, m):
if not sons[root]:
return {0}
child_paths = []
for son in sons[root]:
child_paths.append(dfs(son, sons, dist, m))
result = {0}
# 选择单条路径
for i, paths in enumerate(child_paths):
for length in paths:
total = dist[sons[root][i]] + length
if total <= m:
result.add(total)
# 选择两条路径
for i in range(len(child_paths)):
for j in range(i + 1, len(child_paths)):
for len1 in child_paths[i]:
for len2 in child_paths[j]:
total = dist[sons[root][i]] + dist[sons[root][j]] + len1 + len2
if total <= m:
result.add(total)
return result
while True:
try:
m = int(input())
n = int(input())
sons = defaultdict(list)
father = [-1] * n
dist = [0] * n
for _ in range(n - 1):
u, v, d = map(int, input().split())
sons[u].append(v)
father[v] = u
dist[v] = d
root = next(i for i in range(n) if father[i] == -1)
paths = dfs(root, sons, dist, m)
print(max(paths) if paths else 0)
except EOFError:
break
算法及复杂度
- 算法:DFS + 动态规划
- 时间复杂度: O ( n ⋅ 2 d ) \mathcal{O}(n \cdot 2^d) O(n⋅2d) - n n n 为节点数, d d d 为最大度数
- 空间复杂度: O ( n ) \mathcal{O}(n) O(n) - 需要存储树结构和路径长度

2341

被折叠的 条评论
为什么被折叠?



