【HDU5732 2016 Multi-University Training Contest 1J】【树哈希模板 无根树的同构】Subway 对应两棵树的匹配关系

来源:互联网 发布:学风水看什么书 知乎 编辑:程序博客网 时间:2024/06/07 10:19

Subway

Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 486    Accepted Submission(s): 68
Special Judge


Problem Description
jiefangxuanyan and yiyi cat are universally acknowledged model couples. Once jiefangxuanyan has time, he takes a train to yiyi cat’s city and meet her. This time, as usual, jiefangxuanyan gets out from the railway station, and enters the subway, only to find that the subway stations of the whole city changes their names!

As a direction idiot, jiefangxuanyan felt helpless with this situation. He called yiyi cat for help. Because the subway map is so complicated, she can’t remember it either. Fortunately, only the names of the stations changed, the structure of subway lines is the same. So she picks out the old map to make a mapping.

But mapping such a confused subway map is definitely a difficult task. So she has to use the computer. Unfortunately, she just spilt wonton soup into her computer. So, yiyi cat asked you for help, hoping you can help her with this problem.

The subway in the city forms a tree, with N subway stations and N-1 subway lines. Any pair of stations are connected with one or more subway lines. You need to find a bijective mapping from the old names to the new names, that for each pair of stations connected by exactly one line in the old map, their new names are also connected by exactly one line in the new map.
 

Input
The input has multiple test cases, please process to the end of file.

For each test case, the first line is an integer N(1N100000).

In the following N1 lines, each line has two space-separated string, as two stations connected by one line in the old map.

In the following N1 lines, each line has two space-separated string, as two stations connected by one line in the new map.

Station names are no longer than 10 characters, and only consists of lowercase letters (a~z).
 

Output
For each test case, output N lines.

Each line consists two space-separated string, as the old name and its corresponding new name.

Both the names appeared in the old and new subway map should appear exactly once in the output.

You can output the names in any order. And if there are multiple valid mappings, output any one.

Names in the old map and the new map may be the same, but this does not mean these two stations are the same.
 

Sample Input
3a bb cb aa c
 

Sample Output
b aa bc c
 

Author
HIT
 

Source
2016 Multi-University Training Contest 1
#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<ctype.h>#include<math.h>#include<set>#include<map>#include<vector>#include<queue>#include<bitset>#include<algorithm>#include<time.h>using namespace std;void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;int casenum, casei;int T;map<string, int>mop[2]; int ID[2];string S[2][N];vector<int>a[2][N];vector<int>core[2];char s[10];int n;int O(){scanf("%s", s);if (!mop[T].count(s))mop[T][s] = ++ID[T];int o = mop[T][s]; S[T][o] = s;return o;}int son[N], mxp[N], rt;void coredfs(int x, int fa){son[x] = 1;mxp[x] = 0;for (int i = a[T][x].size() - 1; ~i; --i){int y = a[T][x][i];if (y == fa)continue;coredfs(y, x);son[x] += son[y];gmax(mxp[x], son[y]);}gmax(mxp[x], n - son[x]);if (mxp[x] < mxp[rt]){core[T].clear(); core[T].push_back(rt = x);}else if (mxp[x] == mxp[rt])core[T].push_back(x);}void findcore(){mxp[rt = 0] = 1e9;coredfs(1, 0);if (core[T].size() < 1 || core[T].size() > 2)while (1);}const int MAGIC = 111111;UL powMod(UL x, int p){UL y = 1;while (p){if (p & 1)y *= x;x *= x;p >>= 1;}return y;}struct Hash{int o;int len; UL val;Hash() :o(-1), len(0), val(0) {}Hash(char ch) :len(1), val(ch) {}Hash(int l, int v) :len(l), val(v) {}bool operator < (const Hash& b){return val < b.val;}bool operator == (const Hash& b){return len == b.len && val == b.val;}Hash operator + (const Hash&b){return Hash(len + b.len, val * powMod(MAGIC, b.len) + b.val);}};Hash self[2][N];vector<Hash>child[2][N];void GetHash(int x, int fa){child[T][x].clear();for (int i = a[T][x].size() - 1; ~i; --i){int y = a[T][x][i];if (y == fa)continue;GetHash(y, x);child[T][x].push_back(self[T][y]);}sort(child[T][x].begin(), child[T][x].end());self[T][x] = Hash();for (auto & it : child[T][x])self[T][x] = self[T][x] + it;self[T][x] = Hash('(') + self[T][x] + Hash(')');self[T][x].o = x;}void match(int x, int y){//printf("%s %s\n", S[0][x].c_str(), S[1][y].c_str());cout << S[0][x] <<  " " << S[1][y] << "\n";for (int i = child[0][x].size() - 1; ~i; --i){int xx = child[0][x][i].o;int yy = child[1][y][i].o;match(xx, yy);}}void tryit(){for (int i = 0; i < core[0].size(); ++i){for (int j = 0; j < core[1].size(); ++j){int rt0 = core[0][i]; T = 0; GetHash(rt0, 0);int rt1 = core[1][j]; T = 1; GetHash(rt1, 0);if (self[0][rt0] == self[1][rt1]){match(rt0, rt1);return;}}}while (1);//判定是否会出现无法匹配同构的情况}int main(){//fre();while (~scanf("%d", &n)){for (T = 0; T < 2; ++T){for (int i = 1; i <= n; ++i)a[T][i].clear();mop[T].clear(); ID[T] = 0;for (int i = 1; i < n; ++i){int x = O(); int y = O();a[T][x].push_back(y);a[T][y].push_back(x);}findcore();}tryit();}return 0;}/*【trick&&吐槽】妈蛋,这题本来只是一个树同构让我读题读成了求图的同构,自己加大了题目难度。我是sb!知道是求树同构之后,这道题的竟然被我一下子写AC了!【题意】给你一棵树,树上的每个节点对应着一个字符串。告诉你边的联通关系。后来,这棵树的节点可能改了名字,我们再告诉你边的联通关系。也就是说,这两棵树是同构的,只是我们不知道具体的同构关系。问你可能的同构对应关系,并完成节点的匹配【类型】树哈希 树同构【分析】首先,要知道以下性质——树的重心和中心都最多只有2个。于是,我们不妨一个dfs找到树的重心,并把其记录下来。然后,我们知道重心了,便可以做树哈希。树哈希的权值如果相同,说明对应关系找到了。在树哈希成功的基础上,我们递归匹配子儿子的对应关系即可。【时间复杂度&&优化】O(nlogn) log是由于排序导致的*/



1 0
原创粉丝点击