基于Python的cyaron库实现。可以生成若干个二叉树的先序序列。
from cyaron import *
global tree
global ans
def outPut(i):
if i > len(tree) or tree[i] == -1:
ans.append(0)
return
ans.append(tree[i])
outPut(i * 2 + 1)
outPut(i * 2 + 2)
if __name__ == '__main__':
_n = [20, 21, 22, 23, 24, 25, 26]
_m = ['A']
for ii in range(1, 5):
print("working on %d" % ii)
io = IO(file_prefix="test", data_id=ii)
n = _n[ii % len(_n)]
nn = randint(20, 50)
io.input_writeln(nn)
for j in range(nn):
binary_tree = Graph.binary_tree(n)
ans = []
tree = [-1] * pow(2, n)
tree[0] = 1
for edge in binary_tree.iterate_edges():
i = 0
for i in range(0, len(tree)):
if tree[i] == edge.start:
break
if tree[i * 2 + 1] == -1:
tree[i * 2 + 1] = edge.end
else:
tree[i * 2 + 2] = edge.end
outPut(0)
res = ""
for i in ans:
if i == 0:
res += "0"
else:
res += chr(ord(_m[j % len(_m)]) + i - 1)
io.input_writeln(res)
io.output_gen("ans.exe")
基于C++实现,便于生成多组测试数据,本生成器可完美适配赫夫曼树的构建与编码,经过修改后可以适配多种题目。为了避免导致因相同权值造成的多解问题导致的可能答案错误,添加了保证哈夫曼树唯一性的检测函数。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
bool checkOnlySolution(vector<int> const v, int const newNumber) {
set<int> s;
priority_queue<int, vector<int>, greater<>> pq;
for (int i = 0; i < v.size(); i++) {
s.insert(v[i]);
pq.push(v[i]);
}
pq.push(newNumber);
s.insert(newNumber);
while (pq.size() > 1) {
int a = pq.top();
pq.pop();
s.erase(a);
int b = pq.top();
pq.pop();
s.erase(b);
if (s.find(a + b) != s.end()) {
return false;
}
s.insert(a + b);
pq.push(a + b);
}
return true;
}
int main() {
srand(time(NULL) * rand() * (time(NULL) % 10));
freopen("5.in", "w", stdout);
int totalCases = rand() % 10 + 20;
cout << totalCases << endl;
while (totalCases--) {
int totalNumbers = rand() % 80 + 30;
cout << totalNumbers;
vector<int> numbers;
set<int> s;
for (int i = 0; i < totalNumbers; i++) {
int newNumber = rand() % 200 + 1;
if (s.find(newNumber) == s.end() && checkOnlySolution(numbers, newNumber)) {
s.insert(newNumber);
numbers.push_back(newNumber);
} else {
i--;
continue;
}
}
for (int i = 0; i < numbers.size(); i++) {
cout << " " << numbers[i];
}
cout << endl;
}
return 0;
}
基于C++实现,便于生成多组测试数据,本生成器可完美适配赫夫曼树解码,经过修改后可以适配多种题目。为了避免导致因相同权值造成的多解问题导致的可能答案错误,添加了保证哈夫曼树唯一性的检测函数,并使用随机数函数生成有解或无解的测试序列。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class huffman_tree {
public:
struct node {
int freq;
string ch;
node *left, *right;
node(int freq, string ch, node *left, node *right) : freq(freq), ch(ch), left(left), right(right) {}
};
node *root;
vector<pair<string, string>> codes;
huffman_tree(const vector<pair<string, int>> &freq) {
auto cmp = [](node *a, node *b) { return a->freq > b->freq; };
priority_queue<node *, vector<node *>, decltype(cmp)> q(cmp);
for (auto &p: freq) {
q.push(new node(p.second, p.first, nullptr, nullptr));
}
while (q.size() > 1) {
node *a = q.top();
q.pop();
node *b = q.top();
q.pop();
q.push(new node(a->freq + b->freq, "0", a, b));
}
root = q.top();
q.pop();
dfs(root, "");
}
void dfs(node *root, string s) {
if (root->left == nullptr && root->right == nullptr) {
codes.push_back({root->ch, s});
return;
}
dfs(root->left, s + "0");
dfs(root->right, s + "1");
}
};
bool checkOnlySolution(vector<int> const v, int const newNumber) {
set<int> s;
priority_queue<int, vector<int>, greater<>> pq;
for (int i = 0; i < v.size(); i++) {
s.insert(v[i]);
pq.push(v[i]);
}
pq.push(newNumber);
s.insert(newNumber);
while (pq.size() > 1) {
int a = pq.top();
pq.pop();
s.erase(a);
int b = pq.top();
pq.pop();
s.erase(b);
if (s.find(a + b) != s.end()) {
return false;
}
s.insert(a + b);
pq.push(a + b);
}
return true;
}
vector<string> solve(vector<int> v) {
vector<int> temp(v);
sort(temp.begin(), temp.end());
vector<pair<string, int>> freq;
for (int i = 0; i < v.size(); i++) {
freq.emplace_back(to_string(temp[i]), temp[i]);
}
huffman_tree tree(freq);
vector<string> res;
for (int i = 0; i < v.size(); i++) {
res.push_back(tree.codes[i].second);
}
return res;
}
int main() {
srand(time(NULL) * rand() * (time(NULL) % 10));
int totalCases = rand() % 10 + 10;
cout << totalCases << endl;
vector<char> encodeChars;
for (int i = 0; i < 26; i++) {
encodeChars.push_back('a' + i);
encodeChars.push_back('A' + i);
}
while (totalCases--) {
shuffle(encodeChars.begin(), encodeChars.end(), default_random_engine(rand()));
int totalNumbers = rand() % 35 + 15;
cout << totalNumbers;
vector<int> numbers;
set<int> s;
for (int i = 0; i < totalNumbers; i++) {
int newNumber = rand() % 200 + 1;
if (s.find(newNumber) == s.end() && checkOnlySolution(numbers, newNumber)) {
s.insert(newNumber);
numbers.push_back(newNumber);
} else {
i--;
continue;
}
}
for (int i = 0; i < numbers.size(); i++) {
cout << " " << numbers[i];
}
cout << endl;
for (int i = 0; i < numbers.size(); i++) {
if (i) {
cout << " ";
}
cout << encodeChars[i];
}
cout << endl;
int totalQueries = rand() % 10 + 5;
cout << totalQueries << endl;
while (totalQueries--) {
bool hasSolution = rand() % 5 != 0;
if (hasSolution) {
vector<string> solutions(solve(numbers));
shuffle(solutions.begin(), solutions.end(), default_random_engine(rand()));
for (int i = 0; i < rand() % 30 + 20; i++) {
cout << solutions[rand() % solutions.size()];
}
} else {
for (int i = 0; i < rand() % 50 + 50; i++) {
cout << rand() % 2;
}
}
cout << endl;
}
}
return 0;
}
基于C++实现,便于生成多组测试数据,本生成器可完美适配DS森林叶子编码,经过修改后可以适配多种OJ题,便于生成测试数据进行对拍。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
vector<int> getTree(int const numOfNodes, int const numOfBranch) {
vector<int> res;
map<int, int> m;
vector<int> positions;
positions.push_back(0);
for (int i = 0; i < numOfNodes; i++) {
for (int j = 0; j < positions.size(); j++) {
swap(positions[rand() % positions.size()], positions[rand() % positions.size()]);
}
res.push_back(positions.front());
for (int j = 0; j < numOfBranch; j++) {
positions.push_back(positions.front() * numOfBranch + j + 1);
}
positions.erase(positions.begin());
}
sort(res.begin(), res.end());
return res;
}
void prePost(vector<int> &res, vector<int> tree, int numOfBranch, int node);
vector<int> getPrePost(vector<int> tree, int const numOfBranch) {
vector<int> res;
prePost(res, tree, numOfBranch, 0);
return res;
}
void prePost(vector<int> &res, vector<int> const tree, int const numOfBranch, int const node) {
int i = 0;
for (; i < tree.size() && node > tree[i]; i++) {
if (tree[i] == node) {
break;
}
}
if (i == tree.size() || node != tree[i]) {
res.push_back(-1);
return;
}
res.push_back(node);
for (int j = 0; j < numOfBranch; j++) {
prePost(res, tree, numOfBranch, node * numOfBranch + j + 1);
}
}
int main() {
srand(time(NULL) * rand() * (time(NULL) % 10));
int numOfTrees = 4, numOfBranch = 6;
cout << numOfTrees << " " << numOfBranch << endl;
int cnt = 0;
for (int i = 0; i < numOfTrees; i++) {
int upper_bound = rand() % ((52 - cnt) / (numOfTrees - i) / 3) + (52 - cnt) / (numOfTrees - i) / 3;
int lower_bound = numOfBranch + 1;
int numOfNodes = 0;
if (upper_bound <= lower_bound) {
numOfNodes = upper_bound;
} else {
numOfNodes = rand() % (upper_bound - lower_bound) + lower_bound;
}
vector<int> res = getPrePost(getTree(numOfNodes, numOfBranch), numOfBranch);
for (int j = 0; j < res.size(); j++) {
if (j) {
cout << " ";
}
if (res[j] >= 0) {
if (cnt < 26) {
cout << (char) ('A' + cnt);
} else {
cout << (char) ('a' + cnt - 26);
}
cnt++;
} else {
cout << "0";
}
}
cout << endl;
}
return 0;
}
基于C++实现,生成使用孩子链表法表示的多叉树,可以直接适配树的后根遍历(孩子链表法)
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main() {
srand(time(NULL) * rand() * (time(NULL) % 10));
int numOfNodes = 50;
int indexOfRoot = rand() % numOfNodes;
set<int> s;
vector<int> nodes;
vector<vector<int>> graph(numOfNodes);
s.insert(indexOfRoot);
nodes.push_back(indexOfRoot);
while (nodes.size() < numOfNodes) {
int i = rand() % numOfNodes;
while (s.find(i) != s.end()) {
i = rand() % numOfNodes;
}
graph[nodes[rand() % nodes.size()]].push_back(i);
s.insert(i);
nodes.push_back(i);
}
for (int i = 0; i < numOfNodes; i++) {
sort(graph[i].begin(), graph[i].end());
}
cout << numOfNodes << " " << indexOfRoot << endl;
for (int i = 0; i < numOfNodes; i++) {
if (i < 26) {
cout << (char) (i + 'A') << " ";
} else {
cout << (char) (i - 26 + 'a') << " ";
}
for (int j = 0; j < graph[i].size(); j++) {
cout << graph[i][j] << " ";
}
cout << "-1" << endl;
}
return 0;
}
基于C++实现,生成使用双亲表示法表示的多叉树,可以直接适配树的先序遍历(双亲表示法)
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main() {
srand(time(NULL) * rand() * (time(NULL) % 10));
int T = 100;
cout << T << endl;
while (T--) {
int numOfNodes = rand() % 30 + 21;
int indexOfRoot = rand() % numOfNodes;
set<int> s;
vector<int> nodes;
vector<vector<int>> graph(numOfNodes);
s.insert(indexOfRoot);
nodes.push_back(indexOfRoot);
while (nodes.size() < numOfNodes) {
int i = rand() % numOfNodes;
while (s.find(i) != s.end()) {
i = rand() % numOfNodes;
}
graph[nodes[rand() % nodes.size()]].push_back(i);
s.insert(i);
nodes.push_back(i);
}
for (int i = 0; i < numOfNodes; i++) {
sort(graph[i].begin(), graph[i].end());
}
cout << numOfNodes << endl;
cout << "A";
for (int i = 1; i < numOfNodes; i++) {
if (i < 26) {
cout << " " << (char) (i + 'A');
} else {
cout << " " << (char) (i - 26 + 'a');
}
}
cout << endl;
for (int i = 0; i < numOfNodes; i++) {
if (i) {
cout << " ";
}
if (i == indexOfRoot) {
cout << "-1";
} else {
for (int f = 0; f < nodes.size(); f++) {
for (int j = 0; j < graph[f].size(); j++) {
if (graph[f][j] == i) {
cout << f;
f = nodes.size();
break;
}
}
}
}
}
cout << endl;
}
return 0;
}
基于Python实现,用于生成图的邻接表表示法的测试数据。
from cyaron import *
if __name__ == '__main__':
for ii in range(1, 6):
print("working on %d" % ii)
io = IO(file_prefix="", data_id=ii)
T = randint(20, 30)
io.input_writeln(T)
for i in range(T):
n = randint(20, 25)
m = randint(3 * n, 6 * n)
io.input_writeln(n, m)
graph = Graph.graph(n, m, self_loop=False, repeated_edges=False)
seq = [chr(ord('A') + i) for i in range(0, n)]
ans = ""
for i in seq:
ans += str(i) + " "
io.input_writeln(ans.strip())
edges = []
for edge in graph.iterate_edges():
edges.append(chr(ord('A') - 1 + edge.start) + " " + chr(ord('A') - 1 + edge.end))
edges.sort()
for i in edges:
io.input_writeln(i)
from cyaron import *
if __name__ == '__main__':
for ii in range(1, 6):
print("working on %d" % ii)
io = IO(file_prefix="", data_id=ii)
T = randint(20, 30)
io.input_writeln(T)
for i in range(T):
n = randint(20, 25)
m = randint(3 * n, 6 * n)
io.input_writeln(n)
graph = Graph.graph(n, m, self_loop=False, repeated_edges=False)
g = [[0 for ii in range(n)] for jj in range(n)]
for edge in graph.iterate_edges():
g[edge.start - 1][edge.end - 1] = 1
g[edge.end - 1][edge.start - 1] = 1
ans = str(g).replace('[', '').replace(']', '\n').replace(',', '').replace('\n ', '\n').strip()
io.input_writeln(ans)
from itertools import product
from random import shuffle
from cyaron import *
if __name__ == '__main__':
for ii in range(1, 6):
print("working on %d" % ii)
io = IO(file_prefix="", data_id=ii)
T = randint(10, 20)
io.input_writeln(T)
letters = "abcdefghijklmnopqrstuvwxyz"
letters += letters.upper()
letters_combinations = ["".join(x) for x in product(letters, repeat=2)]
for i in range(T):
shuffle(letters_combinations)
n = randint(20, 25)
m = randint(2 * n, 10 * n)
tmp = randint(1, 100)
al = [n]
for j in range(n):
al.append(letters_combinations[j])
io.input_writeln(al)
graph = Graph.graph(n, m, directed=True, self_loop=False, repeated_edges=False, weight_limit=(10, 100))
g = [[0 for ii in range(n)] for jj in range(n)]
for edge in graph.iterate_edges():
g[edge.start - 1][edge.end - 1] = edge.weight
matrix = str(g).replace('[', '').replace(']', '\n').replace(',', '').replace('\n ', '\n').strip()
io.input_writeln(matrix)
io.input_writeln(letters_combinations[randint(0, n)])
io.output_gen("ans.exe")
from itertools import product
from random import shuffle
from cyaron import *
from random import shuffle as sl
from random import randint as rd
def random_graph(node, edge):
n = node
node = range(0, n)
node = list(node)
sl(node) # 生成拓扑排序
m = edge
result = [] # 存储生成的边,边用tuple的形式存储
appeared_node = []
not_appeared_node = node
# 生成前n - 1条边
while len(result) != n - 1:
# 生成第一条边
if len(result) == 0:
p1 = rd(0, n - 2)
p2 = rd(p1 + 1, n - 1)
x = node[p1]
y = node[p2]
appeared_node.append(x)
appeared_node.append(y)
not_appeared_node = list(set(node).difference(set(appeared_node)))
result.append((x, y))
# 生成后面的边
else:
p1 = rd(0, len(appeared_node) - 1)
x = appeared_node[p1] # 第一个点从已经出现的点中选择
p2 = rd(0, len(not_appeared_node) - 1)
y = not_appeared_node[p2]
appeared_node.append(y) # 第二个点从没有出现的点中选择
not_appeared_node = list(set(node).difference(set(appeared_node)))
# 必须保证第一个点的排序在第二个点之前
if node.index(y) < node.index(x):
result.append((y, x))
else:
result.append((x, y))
# 生成后m - n + 1条边
while len(result) != m:
p1 = rd(0, n - 2)
p2 = rd(p1 + 1, n - 1)
x = node[p1]
y = node[p2]
# 如果该条边已经生成过,则重新生成
if (x, y) in result:
continue
else:
result.append((x, y))
mat = [[0] * n for i in range(n)]
for i in range(len(result)):
mat[result[i][0]][result[i][1]] = 1
return node, list(result), mat
if __name__ == '__main__':
for ii in range(1, 6):
print("working on %d" % ii)
io = IO(file_prefix="", data_id=ii)
T = randint(10, 20)
io.input_writeln(T)
for i in range(T):
n = randint(20, 25)
m = randint(n, int(2 * n))
io.input_writeln(n)
tp, edges, graph = random_graph(n, m)
matrix = str(graph).replace('[', '').replace(']', '\n').replace(',', '').replace('\n ', '\n').strip()
io.input_writeln(matrix)
io.output_gen("ans.exe")