Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include "math.h"
- #include <limits>
- #include <random>
- #include <list>
- #include <queue>
- #include <stack>
- #include <random>
- #include <algorithm>
- using std::cin;
- using std::cout;
- using std::endl;
- using std::vector;
- using std::list;
- using std::queue;
- using std::stack;
- const int BUF_LEN = 1e7;
- char buf[BUF_LEN];
- int cnt;
- void * operator new(size_t len)
- {
- void * p = (void *)(buf + cnt);
- cnt += len;
- return p;
- }
- void operator delete(void * p)
- {
- }
- struct edge{
- size_t a_, b_;
- edge() = default;
- edge(size_t a_, size_t b_) {
- this->a_ = a_;
- this->b_ = b_;
- }
- };
- int n_;
- vector<edge> g1, g2;
- vector<size_t> degree1, degree2;
- vector<vector<size_t>> v_list1, v_list2;
- //stack<size_t> order1, order2;
- void read_data() {
- cin >> n_;
- g1.resize(n_ - 1);
- degree1.resize(n_ + 1);
- v_list1.resize(n_ + 1);
- for (int i = 0; i < n_ - 1; ++i) {
- cin >> g1[i].a_ >> g1[i].b_;
- degree1[g1[i].a_]++;
- degree1[g1[i].b_]++;
- v_list1[g1[i].a_].push_back(g1[i].b_);
- v_list1[g1[i].b_].push_back(g1[i].a_);
- }
- g2.resize(n_ - 1);
- degree2.resize(n_ + 1);
- v_list2.resize(n_ + 1);
- for (int i = 0; i < n_ - 1; ++i) {
- cin >> g2[i].a_ >> g2[i].b_;
- degree2[g2[i].a_]++;
- degree2[g2[i].b_]++;
- v_list2[g2[i].a_].push_back(g2[i].b_);
- v_list2[g2[i].b_].push_back(g2[i].a_);
- }
- }
- void create_data(vector<edge> g1, vector<edge> g2) {
- degree1.resize(n_ + 1);
- v_list1.resize(n_ + 1);
- for (int i = 0; i < n_ - 1; ++i) {
- degree1[g1[i].a_]++;
- degree1[g1[i].b_]++;
- v_list1[g1[i].a_].push_back(g1[i].b_);
- v_list1[g1[i].b_].push_back(g1[i].a_);
- }
- degree2.resize(n_ + 1);
- v_list2.resize(n_ + 1);
- for (int i = 0; i < n_ - 1; ++i) {
- degree2[g2[i].a_]++;
- degree2[g2[i].b_]++;
- v_list2[g2[i].a_].push_back(g2[i].b_);
- v_list2[g2[i].b_].push_back(g2[i].a_);
- }
- }
- struct vertex_level{
- size_t vertex, level;
- vertex_level() = default;
- vertex_level(size_t vertex,size_t level){
- this -> vertex = vertex;
- this -> level = level;
- }
- };
- vector<size_t> find_center(const vector<edge>& g_, vector<size_t>& degree_,
- vector<vector<size_t>>& v_list_) {
- vector<size_t> center;
- queue<vertex_level> v_;
- for (int i = 1; i < n_ + 1; i++) {
- if (degree_[i] == 1) v_.push(vertex_level(i, 1));
- }
- vertex_level last;
- while (v_.size() > 1) {
- last = v_.front();
- //order_.push(last.vertex);
- v_.pop();
- degree_[last.vertex]--;
- for (auto j : v_list_[last.vertex]) {
- if (degree_[j] > 0) {
- degree_[j]--;
- if (degree_[j] == 1) {
- v_.push(vertex_level(j, last.level + 1));
- }
- }
- }
- }
- center.push_back(v_.front().vertex);
- if (last.level == v_.front().level) {
- center.push_back(last.vertex);
- }
- return center;
- }
- struct node {
- size_t num, hash;
- vector<node*> childs;
- node* parent;
- ~node() {
- if (childs.size() > 0) {
- for (auto i : childs){
- delete i;
- }
- }
- }
- };
- node* newNode(size_t data, node* parent)
- {
- node* newnode = new node;
- newnode->num = data;
- newnode->hash = 0;
- newnode->parent = parent;
- //newnode->childs = default();
- return newnode;
- }
- node* constructTreeUtil_(size_t center, vector<size_t>& degree_, vector<vector<size_t>>& v_list_, vector<bool>& col, node* parent) {
- node* root = newNode(center, parent);
- degree_[center]--;
- col[center] = 1;
- if (degree_[center] == 0) return root;
- for (auto i : v_list_[center]) {
- if (degree_[i] > 0 && col[i] == 0) {
- root->childs.push_back(constructTreeUtil_(i, degree_, v_list_, col, root));
- }
- }
- return root;
- }
- node* constructTreeUtil(vector<size_t>& center, vector<size_t>& degree_,
- vector<vector<size_t>>& v_list_, node* parent) {
- vector<bool> color;
- color.resize(n_ + 1);
- if (center.size() == 2) {
- degree_[0]+= 2;
- for (int i = 0; i < v_list_[center[0]].size(); ++i){
- if (v_list_[center[0]][i] == center[1]) v_list_[center[0]][i] = 0;
- }
- for (int i = 0; i < v_list_[center[1]].size(); ++i){
- if (v_list_[center[1]][i] == center[0]) v_list_[center[1]][i] = 0;
- }
- v_list_[0].push_back(center[0]);
- v_list_[0].push_back(center[1]);
- center.clear();
- center.push_back(0);
- }
- return constructTreeUtil_(center[0], degree_, v_list_, color, parent);
- }
- bool compare_node_by_hash(const node* a, const node* b) {
- return (a->hash > b->hash);
- }
- const int64_t prime = 196613;
- size_t hash_func( size_t key )
- {
- key += ~(key << 32);
- key ^= (key >> 10);
- key += (key << 6);
- key ^= (key >> 27);
- key += ~(key << 18);
- key ^= (key >> 33);
- return key;
- }
- int64_t hash_tree(node* root) {
- int64_t hash = (hash_func(static_cast<int64_t>(root->childs.size())) % prime + 27) % prime; // какая-то функция
- for (int i = 0; i < root->childs.size(); ++i) {
- hash = (hash + 2 * hash_func((static_cast<int64_t>(hash_tree(root->childs[i])))) % prime) % prime; //pow(3, i)
- }
- hash = hash % prime;
- root->hash = static_cast<size_t>(hash);
- std::sort(root->parent->childs.begin(), root->parent->childs.end(), compare_node_by_hash);
- return hash;
- }
- /*int64_t hash_tree(node* root, size_t level) {
- int64_t hash = (static_cast<int64_t>(root->childs.size()) % prime + 27) % prime; // какая-то функция
- for (int i = 0; i < root->childs.size(); ++i) {
- hash = (hash + (static_cast<int64_t>(hash_tree(root->childs[i], level + 1))
- * primes[level % primes.size()]) % prime) % prime; //pow(3, i)
- }
- hash = hash % prime;
- root->hash = static_cast<size_t>(hash);
- std::sort(root->parent->childs.begin(), root->parent->childs.end(), compare_node_by_hash);
- return hash;
- }*/
- bool biection(node* root1, node* root2, vector<int>& ans, vector<bool>& take1, vector<bool>& take2) {
- take1[root1->num] = 1;
- take2[root2->num] = 1;
- ans[root1->num] = static_cast<int>(root2->num);
- if (root1->childs.size() != root2->childs.size()) {
- return 0;
- }
- for (int i = 0; i < root1->childs.size(); ++i) {
- if (!take1[root1->childs[i]->num] && !take2[root2->childs[i]->num]) {
- biection(root1->childs[i], root2->childs[i], ans, take1, take2);
- }
- }
- return 1;
- }
- void sort_tree_hash(node* root) {
- std::sort(root->childs.begin(), root->childs.end(), compare_node_by_hash);
- for (auto i : root->childs) {
- sort_tree_hash(i);
- }
- }
- void print_hash(node* root) {
- cout << root->num << " " << root->hash << endl;
- for (auto i : root->childs) {
- print_hash(i);
- }
- }
- vector<int> solve() {
- vector<int> ans;
- vector<size_t> center1 = find_center(g1, degree1, v_list1);
- vector<size_t> center2 = find_center(g2, degree2, v_list2);
- if (center1.size() != center2.size()) {
- ans.push_back(-1);
- return ans;
- }
- node* root_parent1 = new node;
- node* root_parent2 = new node;
- node* root1 = constructTreeUtil(center1, degree1, v_list1, root_parent1);
- node* root2 = constructTreeUtil(center2, degree2, v_list2, root_parent1);
- //std::random_shuffle(primes.begin(), primes.end());
- hash_tree(root1);
- hash_tree(root2);
- // print_hash(root1);
- // cout <<endl;
- // print_hash(root2);
- if (root1->hash != root2->hash) {
- ans.push_back(-1);
- return ans;
- }
- ans.resize(n_ + 1);
- vector<bool> take1, take2;
- take1.resize(n_ + 1);
- take2.resize(n_ + 1);
- //sort_tree_hash(root1);
- //sort_tree_hash(root2);
- if (!biection(root1, root2, ans, take1, take2)) {
- ans.clear();
- ans.push_back(-1);
- return ans;
- }
- //biection(root1, root2, ans, take1, take2);
- delete root1;
- delete root2;
- delete root_parent1;
- delete root_parent2;
- ans.erase(ans.begin());
- ans.pop_back();
- return ans;
- }
- /////////////////////////////////////////////////////////////////////
- vector<edge> MakeTree(size_t num_vertex, size_t tree_index = 0) {
- vector<edge> roads;
- for (size_t city_name = num_vertex - 1; city_name > 0; --city_name) {
- size_t next_city = tree_index % city_name;
- edge tmp(next_city + 1, city_name + 1);
- roads.emplace_back(tmp);
- tree_index /= city_name;
- }
- return roads;
- };
- vector<edge> PermutateTree(vector<edge> Tree) {
- vector<size_t> indexes;
- for (size_t index = 0; index <= Tree.size(); ++index) {
- indexes.push_back(index);
- }
- std::random_shuffle(indexes.begin(), indexes.end());
- /*for (auto ind : indexes) {
- std::cout << ind + 1 << "\n";
- }*/
- for (auto& road : Tree) {
- road.a_ = indexes[road.a_ - 1] + 1;
- road.b_ = indexes[road.b_ - 1] + 1;
- }
- std::random_shuffle(Tree.begin(), Tree.end());
- return Tree;
- };
- //////////////////////////////////////////////////////////////////////////
- void PrintGr(vector<edge> arr) {
- for (auto i : arr) {
- cout << i.a_ << " " << i.b_ << endl;
- }
- cout<<endl;
- };
- int main(int argc, const char * argv[]) {
- std::ios_base::sync_with_stdio(false);
- std::cin.tie(nullptr);
- // ///////////////// TESTING ///////////////////////////////////////
- size_t index_end = 1;
- for (size_t tree_size = 10000; tree_size < 10002; ++tree_size) {
- n_ = tree_size;
- for (size_t tree_index = 0; tree_index < 5; ++ tree_index) {
- vector<edge> road_set_one = MakeTree(tree_size, tree_index);
- vector<edge> road_set_two = PermutateTree(road_set_one);
- g1.clear(); g2.clear();
- degree1.clear(); degree2.clear();
- v_list1.clear(); v_list2.clear();
- g1 = road_set_one;
- g2 = road_set_two;
- create_data(g1, g2);
- const clock_t begin_time = clock();
- vector<int> ans = solve();
- std::cout << float( clock () - begin_time ) / CLOCKS_PER_SEC <<endl;
- if (float( clock () - begin_time ) / CLOCKS_PER_SEC > 1) {
- std::cout << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<<endl;
- }
- if (ans[0] == -1) {
- std::cout << "ERROR! size = " << tree_size << ", index = " << tree_index << "\n";
- //PrintGr(g1);
- //PrintGr(g2);
- } else {
- //std::cout << "TEST OK" << "\n";
- }
- }
- std::cout << "Size " << tree_size << "done!\n";
- index_end *= tree_size;
- }
- // ///////////////////////////////////////////////////////////////////
- /*read_data();
- vector<int> ans = solve();
- for (auto i : ans) {
- cout << i << endl;
- }*/
- return 0;
- }
- /*10
- 5 10
- 6 9
- 3 8
- 3 7
- 2 6
- 2 5
- 1 4
- 1 3
- 1 2
- 3 5
- 5 2
- 7 1
- 7 3
- 9 4
- 9 10
- 3 8
- 8 6
- 7 9*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement