「JSOI2015」isomorphism

传送门

我们还是考虑树哈希来判同构。

但是我们需要使用一些特殊的手段来特殊对待假节点。

由于是无向树,我们首先求出重心,然后以重心为根跑树哈希。

此处我们不计算假节点的个数对子树大小的贡献。需要注意的是无向树可能有两个重心。

树哈希的时候,假节点儿子的哈希值也直接向上贡献(因为假节点有且只有一个儿子)。

这样我们就可以求出一颗无向树的简化树的哈希值,之后的问题就轻松解决了。

参考代码:

#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while ('0' > c || c > '9') f |= c == '-', c = getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
s = f ? -s : s;
} typedef unsigned long long ull;
const int _ = 1e4 + 5;
const ull base = 19491001; int tot, head[_]; struct Edge { int v, nxt; } edge[_ << 1];
inline void Add_edge(int u, int v) { edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; } int m, s[_]; vector < ull > H[_];
int n, real, dgr[_], siz[_], mnx, mx[_]; ull h[_], pow[_], v[_]; inline void dfs1(int u, int f) {
siz[u] = dgr[u] != 2, mx[u] = 0;
for (rg int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].v; if (v == f) continue ;
dfs1(v, u), siz[u] += siz[v], mx[u] = max(mx[u], siz[v]);
}
mx[u] = max(mx[u], real - siz[u]), mnx = min(mnx, mx[u]);
} inline void dfs2(int u, int f) {
for (rg int i = head[u]; i; i = edge[i].nxt)
if (edge[i].v != f) dfs2(edge[i].v, u);
int top = 0;
for (rg int i = head[u]; i; i = edge[i].nxt)
if (edge[i].v != f) v[top++] = h[edge[i].v];
sort(v, v + top), h[u] = top - 1;
for (rg int i = 0; i < top; ++i) h[u] += pow[i] * v[i];
} vector < int > tmp;
inline bool cmp(const int& i, const int& j) { return s[i] < s[j]; } inline bool check(int x) {
for (rg int i = 0; i < tmp.size(); ++i) {
int y = tmp[i];
for (rg int j = 0; j < H[x].size(); ++j)
for (rg int k = 0; k < H[y].size(); ++k)
if (H[x][j] == H[y][k]) return 0;
}
return 1;
} int main() {
#ifndef ONLINE_JUDGE
file("cpp");
#endif
read(m), pow[0] = 1;
for (rg int i = 1; i < _; ++i) pow[i] = pow[i - 1] * base;
for (rg int o = 1; o <= m; ++o) {
read(n);
memset(head + 1, tot = 0, sizeof (int) * n);
memset(dgr + 1, 0, sizeof (int) * n);
for (rg int u, v, i = 1; i < n; ++i)
read(u), read(v), Add_edge(u, v), Add_edge(v, u), ++dgr[u], ++dgr[v];
real = 0;
for (rg int i = 1; i <= n; ++i) real += dgr[i] != 2;
mnx = 2e9, dfs1(1, 0);
s[o] = real, H[o].clear();
for (rg int i = 1; i <= n; ++i)
if (mx[i] == mnx) dfs2(i, 0), H[o].push_back(h[i]);
}
for (rg int i = 1; i <= m; ++i) if (check(i)) tmp.push_back(i);
sort(tmp.begin(), tmp.end(), cmp);
printf("%u\n", tmp.size());
for (rg int i = 0; i < tmp.size(); ++i) printf("%d ", s[tmp[i]]);
return 0;
}

「JSOI2015」isomorphism的更多相关文章

  1. 「JSOI2015」串分割

    「JSOI2015」串分割 传送门 首先我们会有一个贪心的想法:分得越均匀越好,因为长的绝对比短的大. 那么对于最均匀的情况,也就是 \(k | n\) 的情况,我们肯定是通过枚举第一次分割的位置,然 ...

  2. 「JSOI2015」symmetry

    「JSOI2015」symmetry 传送门 我们先考虑构造出原正方形经过 \(4\) 种轴对称变换以及 \(2\) 种旋转变换之后的正方形都构造出来,然后对所得的 \(7\) 个正方形都跑一遍二维哈 ...

  3. 「JSOI2015」地铁线路

    「JSOI2015」地铁线路 传送门 第一问很简单:对于每条线路建一个点,然后所有该条线路覆盖的点向它连边,权值为 \(1\) ,然后它向所有线路上的点连边,权值为 \(0\) . 然后,跑一边最短路 ...

  4. 「JSOI2015」染色问题

    「JSOI2015」染色问题 传送门 虽然不是第一反应,不过还是想到了要容斥. 题意转化:需要求满足 \(N + M + C\) 个条件的方案数. 然后我们就枚举三个数 \(i, j, k\) ,表示 ...

  5. 「JSOI2015」圈地

    「JSOI2015」圈地 传送门 显然是最小割. 首先对于所有房子,权值 \(> 0\) 的连边 \(s \to i\) ,权值 \(< 0\) 的连边 \(i \to t\) ,然后对于 ...

  6. 「JSOI2015」最小表示

    「JSOI2015」最小表示 传送门 很显然的一个结论:一条边 \(u \to v\) 能够被删去,当且仅当至少存在一条其它的路径从 \(u\) 通向 \(v\) . 所以我们就建出正反两张图,对每个 ...

  7. 「JSOI2015」套娃

    「JSOI2015」套娃 传送门 考虑贪心. 首先我们假设所有的套娃都互相不套. 然后我们考虑合并两个套娃 \(i\),\(j\) 假设我们把 \(i\) 套到 \(j\) 里面去,那么就可以减少 \ ...

  8. 「JSOI2015」非诚勿扰

    「JSOI2015」非诚勿扰 传送门 我们首先考虑一名女性选中她列表里第 \(x\) 名男性的概率(假设她列表里共有 \(s\) 名男性): \[ P = p \times (1 - p) ^ {x ...

  9. 「JSOI2015」salesman

    「JSOI2015」salesman 传送门 显然我们为了使收益最大化就直接从子树中选大的就好了. 到达次数的限制就是限制了可以选的子树的数量,因为每次回溯上来都会减一次到达次数. 多种方案的判断就是 ...

随机推荐

  1. mysql-sql分析策略及优化

    tranlation事务:从失败中回复到正常状态的方法多个应用并发访问数据库时,提供隔离方法 acid原子性:要么成功.要么失败一致性:数据保持“合理性”隔离型:多个事务同时并发执行,每个事务就像各自 ...

  2. 安装proxmox VE(PVE)教程

    proxmox VE,又叫PVE,全称是 Proxmox Virtual Environment 官网地址:https://www.proxmox.com/en/ 1)在官网下载PVE最新镜像,笔者下 ...

  3. 从原理到方案,一步步讲解web移动端实现自适应等比缩放

    前言 在移动端做自适应,我们常用的有媒体查询,rem ,em,宽度百分比这几种方案.但是都各有其缺点. 首先拿媒体查询来说,在某一个宽度区间内只能使用一种样式,为了适应不同屏幕要,css的代码量就会增 ...

  4. JS点击显示隐藏内容

    JS点击显示隐藏密码 思路:获取元素,判断点击,如果DIV显示就隐藏,如果DIV隐藏就显示出来. 1 if(DIV是显示的){ 2 div.style.display='none'; 3 } 4 el ...

  5. 图解SOAPUI解析WSDL文件

    本文链接:https://blog.csdn.net/qq_16234613/article/details/53143279 新建项目 添加WSDL文件 查看方法 查看XML格式 运行测试  

  6. Flink 应用的一致性保障

    应用一致性保障 在Flink中,会自动做检查点,用于故障时恢复一个应用.在恢复时,application的state信息可以根据最近完成的检查点进行重建,并继续运行.不过,仅将一个applicatio ...

  7. MySQL连接池详解

    使用场景数据库连接是一种关键的.有限的.昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池正是针对 ...

  8. 【转载】C++面试题(1-50)

    转自http://www.jobui.com/mianshiti/it/cpp/5017/ 1.    面向对象的程序设计思想是什么? 答:把数据结构和对数据结构进行操作的方法封装形成一个个的对象. ...

  9. Ubuntu16.04安装TORCS

    下载torch安装包: git clone https://github.com/torch/distro.git torch --recursive 安装依赖库: cd torch/ sudo ba ...

  10. centos7安装Nginx 配置及反向代理

    Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为“engine X”,是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器.Ngin ...