对拍器与数据生成
对拍器模板
1 |
|
1 | //测试的代码,命名为my |
1 | //正确的代码,命名为stand |
关于这个ofstream fout(“input.txt”);以及fout.close(),close最好在不用了就写上以避免不必要的错误。ofstream fout() 的括号里面还可以传递其它参数,这里默认表示为:ofstream fout(“input.txt”,ios::trunc);
表示截断并覆写文件。所有可以表示的参数:
ios::app 添加到文件尾
ios::ate 把文件标志放在末尾而非起始。
ios::trunc 默认. 截断并覆写文件。
ios::nocreate 文件不存在也不创建。
ios::noreplace 文件存在则失败。
通常ios::app用的会比较多,他可以让对拍程序分开输入数据到文件
linux下的对拍
linux下的系统命令与windows的命令不太一样,所以对拍器的写法也要变一下。
其实要改的就只有work函数以及main函数,其他都不需要变
1 |
|
数据生成
通常的数据生成比较容易,但是遇到一些不好处理的输入则需要模板
指定根节点的多叉树/无根树
树的生成要保证边数等于结点树减一,并且不能成环且每个点之间都要联通
输入形式形如:
5
1 2
1 3
2 4
4 5
这种可以用并查集来维护这棵树。
考虑以1为根节点,那么只要对于n到2的每一个节点i,让random(1,i-1)为它的根,可以保证这样不会成环且连通。
如果不要求一定以1为根节点,可以用random_shuffle函数获得一个随机的1~n的排列,然后对应着输出就好。1
2
3
4
5
6
7
8
9
10
11
12
13void build(int n) {
for (int i = n; i >= 2; --i) {
dsu[i] = random(1, i - 1);//生成一颗以1为根节点的树
}
//以上为以1为根,随机还要重新编号对应一下,可以借助随机乱序函数
for (int i = 1; i <= n; ++i) mapp[i] = i;
random_shuffle(mapp + 1, mapp + n + 1);//随机排列
//打印树,必要可以随机边权
fout << n << endl;
for (int i = 2; i <= n; ++i)
fout << mapp[i] << ' ' << mapp[dsu[i]] << endl;
fout.close();
}
形如:
9
1 3 2 4 5
2 2 3 6
3 2 7 9
4 1 8
5 0
6 0
7 0
8 0
9 0
其中2到n+1行的第一列表示第几个节点,第二列表示接来跟着的几个数的总数是所对应的相邻节点的个数。
实现的方法也很简单,第一种形式已经得到了第i个结点对应的父节点,所以可以反过来开一个set数组记录父节点对应的子节点,因为第一种生成的得到的会有重复,所以用set去重。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23void create_dataset() {
ofstream fout("input.txt");
int n = random(1, 100);
fout << n << endl;
cout << n << endl;
//生成一棵以0为根节点的树
for (int i = n; i >= 2; --i) {
son[random(1, i - 1) - 1].insert(i - 1);
}
for (int i = 0; i < n; ++i) {
fout << i << ' ';
cout << i << ' ';
fout << son[i].size() << ' ';
cout << son[i].size() << ' ';
for (int it : son[i]) {
fout << it << ' ';
cout << it << ' ';
}
cout << endl;
}
fout.close();
}