开始计概A下半学期。
This commit is contained in:
1 parent
0cfdc8499c
commit
38e97654e1
31 files changed
+2144
-110
No files matched your search
@@ -0,0 +1,88 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* 带权并查集。权重记录该节点到父节点的边的边权(保证一切根节点权重为 0)
|
||||
*/
|
||||
class DsuWeighted {
|
||||
public:
|
||||
using NodeIdx = int;
|
||||
|
||||
struct Node {
|
||||
NodeIdx parent = -1;
|
||||
int weight = 0;
|
||||
std::size_t size = 1;
|
||||
};
|
||||
|
||||
std::vector<Node> nodes;
|
||||
const int groups_amount;
|
||||
|
||||
explicit DsuWeighted(const std::size_t n, int groups = 2) : nodes(n), groups_amount(groups) {
|
||||
for (auto i = 0; i < n; i++) {
|
||||
nodes[i].parent = i;
|
||||
}
|
||||
}
|
||||
|
||||
NodeIdx find(const NodeIdx x) {
|
||||
if (nodes[x].parent == x) { return x; }
|
||||
find(nodes[x].parent);
|
||||
nodes[x].weight += nodes[nodes[x].parent].weight;
|
||||
nodes[x].weight %= groups_amount;
|
||||
return nodes[x].parent = find(nodes[x].parent);
|
||||
}
|
||||
|
||||
int get_weight(const NodeIdx x) {
|
||||
find(x);
|
||||
return nodes[x].weight;
|
||||
}
|
||||
|
||||
void unite(NodeIdx x, NodeIdx y, int weight_delta = 0) {
|
||||
auto x_root = find(x), y_root = find(y);
|
||||
if (x_root == y_root) { return; }
|
||||
if (nodes[x_root].size > nodes[y_root].size) {
|
||||
std::swap(x, y);
|
||||
std::swap(x_root, y_root);
|
||||
weight_delta = -weight_delta;
|
||||
}
|
||||
nodes[x_root].weight += weight_delta + nodes[y].weight - nodes[x].weight;
|
||||
nodes[x_root].weight %= groups_amount;
|
||||
nodes[x_root].parent = y_root;
|
||||
nodes[y_root].size += nodes[x_root].size;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
std::cout.tie(nullptr);
|
||||
|
||||
int test_cases_amount;
|
||||
std::cin >> test_cases_amount;
|
||||
while (test_cases_amount--) {
|
||||
int cases_amount, queries_amount;
|
||||
std::cin >> cases_amount >> queries_amount;
|
||||
|
||||
DsuWeighted dsu(cases_amount, 2);
|
||||
while (queries_amount--) {
|
||||
char op;
|
||||
int case_id_1, case_id_2;
|
||||
std::cin >> op >> case_id_1 >> case_id_2;
|
||||
case_id_1--, case_id_2--;
|
||||
if (op == 'D') {
|
||||
dsu.unite(case_id_1, case_id_2, 1);
|
||||
} else if (op == 'A') {
|
||||
if (dsu.find(case_id_1) != dsu.find(case_id_2)) {
|
||||
std::cout << "Not sure yet." << std::endl;
|
||||
} else {
|
||||
if ((dsu.get_weight(case_id_1) - dsu.get_weight(case_id_2)) % 2 == 0) {
|
||||
std::cout << "In the same gang." << std::endl;
|
||||
} else {
|
||||
std::cout << "In different gangs." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using NodeIdx = std::size_t;
|
||||
static constexpr NodeIdx NULL_IDX = static_cast<NodeIdx>(-1);
|
||||
|
||||
template <typename T>
|
||||
class Tree {
|
||||
public:
|
||||
enum class FuncEntry { Pre, Post };
|
||||
|
||||
struct Node {
|
||||
T value;
|
||||
NodeIdx parent = NULL_IDX;
|
||||
std::vector<NodeIdx> children;
|
||||
};
|
||||
|
||||
std::vector<Node> nodes;
|
||||
NodeIdx root = NULL_IDX;
|
||||
|
||||
NodeIdx add_node(const Node& node_obj) {
|
||||
nodes.push_back(node_obj);
|
||||
return nodes.size() - 1;
|
||||
}
|
||||
|
||||
void init_with_dfs(const std::string& dfs_string) {
|
||||
root = add_node({.value = T()});
|
||||
init_with_dfs(dfs_string, 0, root);
|
||||
}
|
||||
|
||||
int get_height() {
|
||||
int depth = -1;
|
||||
dfs([&depth](NodeIdx node, int dfs_depth) { depth = std::max(depth, dfs_depth); });
|
||||
return depth;
|
||||
}
|
||||
|
||||
protected:
|
||||
void init_with_dfs(const std::string& dfs_string, std::size_t s_idx, NodeIdx node) {
|
||||
if (s_idx >= dfs_string.size()) { return; }
|
||||
if (dfs_string[s_idx] == 'd') {
|
||||
auto new_node = add_node({.value = T(), .parent = node});
|
||||
nodes[node].children.push_back(new_node);
|
||||
init_with_dfs(dfs_string, s_idx + 1, nodes[node].children.back());
|
||||
} else {
|
||||
init_with_dfs(dfs_string, s_idx + 1, nodes[node].parent);
|
||||
}
|
||||
}
|
||||
|
||||
void dfs(const std::function<void(NodeIdx, int)>& func,
|
||||
FuncEntry func_entry = FuncEntry::Post,
|
||||
int depth = 0,
|
||||
NodeIdx node = NULL_IDX
|
||||
) {
|
||||
if (depth == 0) { node = root; }
|
||||
if (func_entry == FuncEntry::Pre) { func(node, depth); }
|
||||
for (auto child : nodes[node].children) {
|
||||
dfs(func, func_entry, depth + 1, child);
|
||||
}
|
||||
if (func_entry == FuncEntry::Post) { func(node, depth); }
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class BinaryTree {
|
||||
public:
|
||||
enum class FuncEntry { Pre, In, Post };
|
||||
|
||||
struct Node {
|
||||
T value;
|
||||
NodeIdx parent = NULL_IDX, left = NULL_IDX, right = NULL_IDX;
|
||||
};
|
||||
|
||||
std::vector<Node> nodes;
|
||||
NodeIdx root = -1;
|
||||
|
||||
NodeIdx add_node(Node node_obj) {
|
||||
nodes.push_back(node_obj);
|
||||
return nodes.size() - 1;
|
||||
}
|
||||
|
||||
void init_from_tree(const Tree<T>& tree) {
|
||||
root = add_node({});
|
||||
init_from_tree(tree, tree.root, 0);
|
||||
}
|
||||
|
||||
int get_height() {
|
||||
int depth = -1;
|
||||
dfs([&depth](NodeIdx node, int dfs_depth) { depth = std::max(depth, dfs_depth); });
|
||||
return depth;
|
||||
}
|
||||
|
||||
protected:
|
||||
void init_from_tree(const Tree<T>& tree, NodeIdx binary_tree_node, NodeIdx tree_node) {
|
||||
bool first_child = false;
|
||||
NodeIdx current_parent = NULL_IDX;
|
||||
for (auto child : tree.nodes[tree_node].children) {
|
||||
if (!first_child) {
|
||||
first_child = true;
|
||||
NodeIdx new_node = add_node({.value = T(), .parent = binary_tree_node});
|
||||
nodes[binary_tree_node].left = new_node;
|
||||
current_parent = nodes[binary_tree_node].left;
|
||||
init_from_tree(tree, nodes[binary_tree_node].left, child);
|
||||
continue;
|
||||
}
|
||||
NodeIdx new_node = add_node({.value = T(), .parent = current_parent});
|
||||
nodes[current_parent].right = new_node;
|
||||
current_parent = nodes[current_parent].right;
|
||||
init_from_tree(tree, current_parent, child);
|
||||
}
|
||||
}
|
||||
|
||||
void dfs(const std::function<void(NodeIdx, int)>& func,
|
||||
FuncEntry func_entry = FuncEntry::Pre,
|
||||
int dfs_depth = 0,
|
||||
NodeIdx node = -1
|
||||
) {
|
||||
if (dfs_depth == 0) { node = root; }
|
||||
if (func_entry == FuncEntry::Pre) { func(node, dfs_depth); }
|
||||
if (nodes[node].left != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].left); }
|
||||
if (func_entry == FuncEntry::In) { func(node, dfs_depth); }
|
||||
if (nodes[node].right != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].right); }
|
||||
if (func_entry == FuncEntry::Post) { func(node, dfs_depth); }
|
||||
}
|
||||
};
|
||||
|
||||
struct ManualVoid {};
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
std::cout.tie(nullptr);
|
||||
|
||||
std::string dfs_string;
|
||||
for (int i = 0; std::cin >> dfs_string && dfs_string != "#"; i++) {
|
||||
Tree<ManualVoid> tree;
|
||||
tree.init_with_dfs(dfs_string);
|
||||
BinaryTree<ManualVoid> binary_tree;
|
||||
binary_tree.init_from_tree(tree);
|
||||
std::cout << "Tree " << i + 1 << ": " << tree.get_height() << " => " << binary_tree.get_height() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user