HDU 5732 Subway(2016多校1J,树的重心 + 哈希)
题目链接 2016多校1 Problem J
题意 给定两棵相同的树,但是编号方案不同。求第一棵树上的每个点对应的第二棵树上的点。输出一种方案即可。
首先确定树的直径的中点。两棵树相等意味着两棵树的直径相等。
然而直径有很多条,我们任意求出两棵树的各一条直径并不以为着这两条直径是相对应的。
但是直径的中点一定是相对应的。
确定根结点后对整棵树哈希并进行匹配的这个过程是不难的。
当直径长度为偶数时中点有两个,那么最多做$4$次匹配就可以了。
这个哈希函数要好好设计,很容易产生冲突。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) typedef unsigned long long LL; const LL A = 90918567;
const LL B = 87378051;
const LL mod = 1e9 + 7;
const int N = 1e5 + 10; int a[N], ans[N], father[N], roota[3], rootb[3];
int numa, numb, n, x, y, c1, c2, L, R, cnt;
bool flag;
map <string, int> mp1, mp2;
vector <int> v[N], g[N];
string ss[N], tt[N], s1, s2;
LL c[N], f[N]; void init(){
mp1.clear();
mp2.clear();
rep(i, 0, n + 1) v[i].clear(), g[i].clear();
c1 = 0, c2 = 0;
} int get1(string s){
if (mp1.count(s)) return mp1[s];
mp1[s] = ++c1;
ss[c1] = s;
return c1;
} int get2(string s){
if (mp2.count(s)) return mp2[s];
mp2[s] = ++c2;
tt[c2] = s;
return c2;
} void dfs1(int x, int fa, int now, vector <int> v[N]){
if (now > c1){
c1 = now;
L = x;
} for (auto u : v[x]){
if (u == fa) continue;
dfs1(u, x, now + 1, v);
}
} void dfs2(int x, int fa, int now, vector <int> v[N]){
father[x] = fa;
if (now > c2){
c2 = now;
R = x;
} for (auto u : v[x]){
if (u == fa) continue;
dfs2(u, x, now + 1, v);
}
} void gethash_a(int x, int fa){
vector <LL> val;
for (auto u : v[x]){
if (u == fa) continue;
gethash_a(u, x);
val.push_back(c[u]);
} sort(val.begin(), val.end());
c[x] = B;
for (auto u : val){
c[x] = (c[x] * A ^ u) % mod;
}
} void gethash_b(int x, int fa){
vector <LL> val;
for (auto u : g[x]){
if (u == fa) continue;
gethash_b(u, x);
val.push_back(f[u]);
} sort(val.begin(), val.end()); f[x] = B;
for (auto u : val){
f[x] = (f[x] * A ^ u) % mod;
}
} bool cmp_a(const int &a, const int &b){
return c[a] < c[b];
} bool cmp_b(const int &a, const int &b){
return f[a] < f[b];
} void work(int x, int y, int fa_a, int fa_b){
vector <int> na, nb;
for (auto u : v[x]) if (u != fa_a) na.push_back(u);
for (auto u : g[y]) if (u != fa_b) nb.push_back(u); if ((int)na.size() != (int)nb.size()){
return;
} sort(na.begin(), na.end(), cmp_a);
sort(nb.begin(), nb.end(), cmp_b); int sz = (int)na.size(); rep(i, 0, sz - 1) if (c[na[i]] == f[nb[i]]) ans[na[i]] = nb[i]; rep(i, 0, sz - 1){
int u1 = na[i], u2 = nb[i];
work(u1, u2, x, y);
}
} bool solve(int roota, int rootb){
gethash_a(roota, 0);
gethash_b(rootb, 0); memset(ans, -1, sizeof ans); if (c[roota] != f[rootb]) return false; ans[roota] = rootb;
work(roota, rootb, 0, 0); bool ret = true;
rep(i, 1, n) if (ans[i] == -1){
ret = false;
break;
} return ret;
} void print(){
rep(i, 1, n) cout << ss[i] << " " << tt[ans[i]] << endl;
} int main(){ ios::sync_with_stdio(false); while (cin >> n){ init();
rep(i, 2, n){
cin >> s1 >> s2;
x = get1(s1);
y = get1(s2);
v[x].push_back(y);
v[y].push_back(x);
} rep(i, 2, n){
cin >> s1 >> s2;
x = get2(s1);
y = get2(s2);
g[x].push_back(y);
g[y].push_back(x);
} L = 0, R = 0;
c1 = 0, c2 = 0;
dfs1(1, 0, 0, v);
memset(father, 0, sizeof father);
dfs2(L, 0, 0, v); x = R;
cnt = 0;
numa = 0;
while (true){
a[++cnt] = R;
R = father[R];
if (R == 0) break;
} if (cnt & 1) roota[++numa] = a[(cnt + 1) / 2]; else{
roota[++numa] = a[cnt / 2];
roota[++numa] = a[cnt / 2 + 1];
} L = 0, R = 0;
c1 = 0, c2 = 0;
dfs1(1, 0, 0, g);
memset(father, 0, sizeof father);
dfs2(L, 0, 0, g); x = R;
cnt = 0;
numb = 0;
while (true){
a[++cnt] = R;
R = father[R];
if (R == 0) break;
} if (cnt & 1) rootb[++numb] = a[(cnt + 1) / 2]; else{
rootb[++numb] = a[cnt / 2];
rootb[++numb] = a[cnt / 2 + 1];
} flag = false;
rep(i, 1, numa){
rep(j, 1, numb){
if (solve(roota[i], rootb[j])){
flag = true;
print();
break;
}
}
if (flag) break;
}
} return 0;
}
HDU 5732 Subway(2016多校1J,树的重心 + 哈希)的更多相关文章
- HDU 5726 GCD (2016多校、二分、ST表处理区间GCD、数学)
题目链接 题意 : 给出一个有 N 个数字的整数数列.给出 Q 个问询.每次问询给出一个区间.用 ( L.R ) 表示.要你统计这个整数数列所有的子区间中有多少个和 GCD( L ~ R ) 相等.输 ...
- HDU 5727 Necklace ( 2016多校、二分图匹配 )
题目链接 题意 : 给出 2*N 颗珠子.有 N 颗是阴的.有 N 颗是阳的.现在要把阴阳珠子串成一个环状的项链.而且要求珠子的放置方式必须的阴阳相间的.然后给出你 M 个限制关系.格式为 ( A.B ...
- bzoj 3053 HDU 4347 : The Closest M Points kd树
bzoj 3053 HDU 4347 : The Closest M Points kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差 ...
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 【HDU 5647】DZY Loves Connecting(树DP)
pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...
- HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模
Multiply game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)
hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由 ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
随机推荐
- JavaScript简易学习笔记
学习地址:http://www.w3school.com.cn/js/index.asp 文字版: https://github.com/songzhenhua/github/blob/master/ ...
- ADB连接手机遇到的问题:list of devices attached
今天工作时想尝试一下使用ADB无线连接手机,结果遇到了下面这样的问题,浪费了几十分钟的时间,挺闹心的,因此想分享出来... 首先 第一步:使用USB数据线连接手机,手机弹出选项时,选择仅充电,然后wi ...
- SDK接入注意点
1. 新建的android项目,要把MainActivity.java里生成的东西全部删去,最好只留个onCreate入口方法,不然会产生什么“hello world”,会把自己写的View内的东西覆 ...
- [g2o]C++图优化库
g2o以图模型表达上述最小二乘问题:比较适合解决SLAM问题 http://openslam.org http://wiki.ros.org/g2o
- 【已解决】UBuntu16.04软件中心更新后只有桌面
出现问题之前 安装好系统之后,成功启动系统,根据软件中心提示,升级电脑安装的软件,如下图所示.点击install(安装)开始更新,之后无任何提示,其实这个时候已经出现了升级异常. 呈现问题 操作步骤一 ...
- jQuery遍历 filter()方法
实例 改变所有 div 的颜色,然后向类名为 "middle" 的类添加边框: $("div").css("background", &qu ...
- python 的tempfile学习
import os import tempfile print "building a file name yourself:" filename = '/tmp/guess_my ...
- 脚本,替换ipa里面的资源,并重新打包
今天逯同事说,可以把狂挂传奇打包的项目写成一个脚本,这样就不用担心证书有时不能用的问题了. 然后,像我这么好学的学生,当然要去执行了.(其实,以前他给的建议我都只是听听而已,这次是因为想学点东西了,所 ...
- CSS3的笔记总结
css3 就是css2 的一个升级版本.css2 是用来做效果渲染的,而css3 可以使做出来的效果更佳丰富. C3有兼容性问题,移动端支持稍微要好些. 坚持以下原则: ...
- 初识 HTML5(一)
H5其实就是H4的一个增强版本,我们在利用H5进行网页的构造会更简便,标签语义更简洁明了.首先,我们要理解HTML4,它是HTML的标记+css2+JavaScript的一些基本应用,简言之,就是AP ...