Subway

Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 860    Accepted Submission(s): 126
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(1≤N≤100000).

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

In the following N−1 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
3
a b
b c
b a
a c
 
Sample Output
b a
a b
c c
 
Author
HIT
 
Source
 
 
 
题意:
给两棵树,它们同构,要求为它们找一个双射。
题解:
判树的同构是很经典的了。
首先要找出树的重心。
为了简单起见,当有两个重心时,可以在它们中间加入一个点,这样重心就唯一了。 关于重心一般有三种说法:
1、删掉重心后剩下的子树最大的那个最小。
2、删掉重心后,剩下的子树大小都不超过原树的一半(floor(n/2))。
3、删掉重心后,剩下的子树尽量平衡(最大-最小子树的大小差最小)。
当然很容易证明,第三条是重心的性质而不是条件。
是必要不充分的。
而第一条和第二条是等价的。
当有两个重心时,它们必然连在一起,且子树中最大的那个一样小。 为了简便找出所有重心,一般使用第一条。 找出重心后对树进行hash。
树的hash有两种方法:
1、弄出树的括号序列,孩子子树小的排在前面,然后做字符串hash
在实现时无需将序列真的做出来。
2、对每个节点,它的hashcode为
hashcode[u] = 1 +
sigma(primes[i % numberOfPrimes]^i * hashcode[child[u][i]])
实际上primes只要随便选几个数就行,实现方便。一般不会错。

  

 const int N = ;
int n; struct Bijection {
map<string, int> stringToInt;
map<string, int>::iterator intToString[N];
int tot; inline void init() {
stringToInt.clear(), tot = ;
} inline int queryInt(const string &t) {
if(stringToInt.count(t)) return stringToInt[t];
intToString[tot] = stringToInt.insert(mk(t, tot)).first;
return tot++;
} inline const string& queryString(const int t) const {
return intToString[t]->first;
}
} nameA, nameB; const int PRIMESTOT = ;
const unsigned int PRIMES[PRIMESTOT] = {
,
,
,
,
,
, }; struct cmpByHashCode {
unsigned int *keys;
cmpByHashCode(unsigned int *keys):keys(keys) {}
inline bool operator ()(const int a, const int b) const {
return keys[a] < keys[b];
}
}; struct TreeHash {
/**
* 1. It will find tree's barycentre firstly and treat it as root.
* 2. If it has two barycentres, it will add a new nodes between them.
* 3. Then Hash Every nodes by it subtree's structure.
* 4. O(n * number of primes).
* 5. Choose several primes as keys to hash.
* 6. The number of primes determine the accuracy of hash.
* */ static unsigned int factor[N]; static void prepare(int N) {
unsigned int tmp[PRIMESTOT];
for(int i = ; i < PRIMESTOT; ++i) tmp[i] = PRIMES[i];
for(int i = ; i < N; ++i) {
factor[i] = tmp[i % PRIMESTOT];
tmp[i % PRIMESTOT] *= tmp[i % PRIMESTOT];
}
} int head[N], son[N * ], nex[N * ], tot;
int n;
int rot, bfsList[N], father[N], size[N], maxSubtree[N];
unsigned int hashCode[N];
vector<int> child[N]; inline void init(int m) {
n = m;
for(int i = ; i < n; ++i) head[i] = -;
tot = ;
} inline void addEdge(int u, int v) {
son[tot] = v, nex[tot] = head[u];
head[u] = tot++;
} inline void bfs(int st) {
int len = ;
bfsList[len++] = st, father[st] = -;
for(int idx = ; idx < len; ++idx) {
int u = bfsList[idx];
for(int tab = head[u], v; tab != -; tab = nex[tab])
if(father[u] != (v = son[tab]))
father[v] = u, bfsList[len++] = v;
}
} inline int getBarycentre() {
bfs(); for(int i = ; i < n; ++i) size[i] = ;
for(int i = n - ; i >= ; --i) {
int u = bfsList[i];
++size[u];
if(father[u] != -) size[father[u]] += size[u]; maxSubtree[u] = n - size[u];
for(int tab = head[u], v; tab != -; tab = nex[tab])
if(father[u] != (v = son[tab]))
maxSubtree[u] = max(maxSubtree[u], size[v]);
} int rot = ;
for(int i = ; i < n; ++i)
if(maxSubtree[rot] > maxSubtree[i]) rot = i;
int anotherRot = -;
for(int i = ; i < n; ++i)
if(i != rot && maxSubtree[rot] == maxSubtree[i]) {
anotherRot = i;
break;
} if(anotherRot != -) {
int newRot = n++;
head[newRot] = -;
addEdge(newRot, rot), addEdge(newRot, anotherRot); for(int tab = head[rot]; tab != -; tab = nex[tab])
if(son[tab] == anotherRot) {
son[tab] = newRot;
break;
}
for(int tab = head[anotherRot]; tab != -; tab = nex[tab])
if(son[tab] == rot) {
son[tab] = newRot;
break;
} rot = newRot;
}
return rot;
} inline int hashTree() {
int rot = getBarycentre();
bfs(rot); for(int i = n - ; i >= ; --i) {
int u = bfsList[i]; child[u].clear(), hashCode[u] = ;
for(int tab = head[u], v; tab != -; tab = nex[tab])
if(father[u] != (v = son[tab])) child[u].push_back(v);
sort(all(child[u]), cmpByHashCode(hashCode));
for(int idx = ; idx < sz(child[u]); ++idx)
hashCode[u] += factor[idx] * hashCode[child[u][idx]];
}
return rot;
}
} treeA, treeB;
unsigned int TreeHash::factor[N]; inline void init() {
nameA.init(), nameB.init(), treeA.init(n), treeB.init(n);
} inline void buildBijection(int u, int v) {
if(u < n && v < n)
cout << nameA.queryString(u) << ' ' << nameB.queryString(v) << "\n";
for(int i = ; i < sz(treeA.child[u]); ++i)
buildBijection(treeA.child[u][i], treeB.child[v][i]);
} inline void solve() {
int u = treeA.hashTree(), v = treeB.hashTree();
buildBijection(u, v);
} int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
TreeHash::prepare(N);
while(cin >> n) {
init();
for(int i = ; i < n; ++i) {
string a, b;
cin >> a >> b;
int u = nameA.queryInt(a), v = nameA.queryInt(b);
treeA.addEdge(u, v), treeA.addEdge(v, u);
}
for(int i = ; i < n; ++i) {
string a, b;
cin >> a >> b;
int u = nameB.queryInt(a), v = nameB.queryInt(b);
treeB.addEdge(u, v), treeB.addEdge(v, u);
}
solve();
}
return ;
}
 

2016 Multi-University Training Contest 1 J.Subway的更多相关文章

  1. 2016 Al-Baath University Training Camp Contest-1 J

    Description X is fighting beasts in the forest, in order to have a better chance to survive he's gon ...

  2. 2016 Al-Baath University Training Camp Contest-1

    2016 Al-Baath University Training Camp Contest-1 A题:http://codeforces.com/gym/101028/problem/A 题意:比赛 ...

  3. 2016 Al-Baath University Training Camp Contest-1 E

    Description ACM-SCPC-2017 is approaching every university is trying to do its best in order to be th ...

  4. 2016-2017 CT S03E05: Codeforces Trainings Season 3 Episode 5 (2016 Stanford Local Programming Contest, Extended) J

    链接:http://codeforces.com/gym/101116 题意:给出n个点,要求一个矩形框将(n/2)+1个点框住,要面积最小 解法:先根据x轴选出i->j之间的点,中间的点(包括 ...

  5. 2016 Al-Baath University Training Camp Contest-1 F

    Description Zaid has two words, a of length between 4 and 1000 and b of length 4 exactly. The word a ...

  6. 2016 Al-Baath University Training Camp Contest-1 A

    Description Tourist likes competitive programming and he has his own Codeforces account. He particip ...

  7. [CFGym101028] 2016 Al-Baath University Training Camp Contest-1

    比赛链接:http://codeforces.com/gym/101028/ 由于实习,几乎没有时间刷题了.今天下午得空,断断续续做了这一套题,挺简单的. A.读完题就能出结果. /* ━━━━━┒ギ ...

  8. 2014 Multi-University Training Contest 1 - J Rating

    题目链接: pid=4870">http://acm.hdu.edu.cn/showproblem.php?pid=4870 题目大意: 题意:一个人注冊两个账号,初始rating都是 ...

  9. 2016 Al-Baath University Training Camp Contest-1 I

    Description It is raining again! Youssef really forgot that there is a chance of rain in March, so h ...

随机推荐

  1. AP(affinity propagation)研究

    待补充…… AP算法,即Affinity propagation,是Brendan J. Frey* 和Delbert Dueck于2007年在science上提出的一种算法(文章链接,维基百科) 现 ...

  2. 以空白符结尾的 alias

    网上经常有人问这个问题:为什么我写的 alias 在 sudo 下就不管用了? $ alias 'll=ls -l' $ sudo ll a-private-dir sudo: ll: command ...

  3. BZOJ1264——[AHOI2006]基因匹配Match

    1.题意,求最长公共子序列,每个数字在序列中都出现5次 2.分析:最长公共子序列的标准解法是dp,$O(n^2)$过不了的,然后我们发现判断哪两个位置优化的地方用$5n$就可以搞定了,那么我们用BIT ...

  4. [转载]Java数组扩容算法及Java对它的应用

    原文链接:http://www.cnblogs.com/gw811/archive/2012/10/07/2714252.html Java数组扩容的原理 1)Java数组对象的大小是固定不变的,数组 ...

  5. angular-ui-bootstrap-modal必须要说的几个点(转)

    angular-ui-bootstrap-modal必须要说的几个点 摘要: 基于angular来实现的一个bootstrap模态框,有些不得不说的地方 项目中以前就经常用到模态框,但是一直没有时间来 ...

  6. BZOJ 4576: [Usaco2016 Open]262144

    Description 一个序列,每次可以将两个相同的数合成一个数,价值+1,求最后最大价值 \(n \leqslant 262144\) Sol DP. 这道题是 BZOJ 4580: [Usaco ...

  7. 【JSOI2007】麻将 bzoj 1028

    Description 麻 将是中国传统的娱乐工具之一.麻将牌的牌可以分为字牌(共有东.南.西.北.中.发.白七种)和序数牌(分为条子.饼子.万子三种花色,每种花色各有一到 九的九种牌),每种牌各四张 ...

  8. Eclipse自动编译问题

    今天遇到一个很郁闷的问题,在程序中修改了一个String字符串,结果打断点是发现,还是修改之前的值,一点都没有变,最终发现该类在tomcat中的class的大小一直都没有变,只有修改时间在变,这才意识 ...

  9. 解决ThinkPHP Call to a member function assign() on a non-object

    <ignore_js_op> assign是tp模板输出变量的一个方法.没有object只能说没实例化...<ignore_js_op> 经过几番思索,终于发现了.原来是Act ...

  10. 【Network】UDP 大包怎么发? MTU怎么设置?

    这里主要用UDP来发送视频,当发送的数据大于1500时分包发送,保证每包小于1500.发送好办,分割后循环发就可以了,关键是接收时的处理.先做一下处理的方法 :发送时每包上面加上标识,比如RTP的做法 ...