题意:给定一棵n个点的树,问删去某个点之后所有的树同构,这样分割出来的树最多能有几棵

n<=4000

思路:分割成至少两个size相等的联通块之后size必定小于n/2,与树的重心的定义相同

预处理出重心(0,1或2个)之后上无根树同构板子

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,ll>P;
#define N 200010
#define M 1000000
#define INF 1e9
#define fi first
#define se second
#define MP make_pair
#define pb push_back
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1
#define fors(i) for(auto i:e[x]) if(i!=p) const int MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int dx[]={-,,,};
int dy[]={,,-,}; int head[N],vet[N],nxt[N],sz[N],mx[N],d[N],tot,Size,root; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} ll readll()
{
ll v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void add(int a,int b)
{
nxt[++tot]=head[a];
vet[tot]=b;
head[a]=tot;
} void dfs1(int u,int fa)
{
int e=head[u];
sz[u]=,mx[u]=;
while(e)
{
int v=vet[e];
if(v!=fa)
{
dfs1(v,u);
sz[u]+=sz[v];
mx[u]=max(mx[u],sz[v]);
}
e=nxt[e];
}
} int ra[N]; int pw(int x,int y)
{
int res=;
while(y)
{
if(y&) res=1ll*res*x%MOD;
x=1ll*x*x%MOD;
y>>=;
}
return res;
} int inv(int x)
{
return pw(x,MOD-);
} struct Sub
{
VI S;
int d1,d2,H1,H2;
Sub(){d1=d2=; S.clear();} void add(int d,int v)
{
S.pb(v);
if(d>d1) d2=d1,d1=d;
else if(d>d2) d2=d;
} int Hash()
{
H1=H2=;
for(int i:S)
{
H1=1ll*H1*(ra[d1]+i)%MOD;
H2=1ll*H2*(ra[d2]+i)%MOD;
}
return H1;
} PII del(int d,int v)
{
if(d==d1) return {d2+,1ll*H2*inv(ra[d2]+v)%MOD};
return {d1+,1ll*H1*inv(ra[d1]+v)%MOD};
}
}; PII U[N];
int n,i,x,y,A[N];
Sub T[N]; void prepare(int n)
{
rep(i,,n) ra[i]=rand()%MOD;
} void dfsD(int u,int p)
{
Size++;
T[u]=Sub();
int e=head[u];
while(e)
{
int v=vet[e];
if(v!=p)
{
dfsD(v,u);
T[u].add(T[v].d1+,T[v].H1);
}
e=nxt[e];
}
T[u].Hash();
} void dfsU(int u,int p)
{
if(p!=root) T[u].add(U[u].fi,U[u].se);
A[u]=T[u].Hash();
int e=head[u];
while(e)
{
int v=vet[e];
if(v!=p)
{
U[v]=T[u].del(T[v].d1+,T[v].H1);
dfsU(v,u);
}
e=nxt[e];
}
} int isok(int root,int block)
{
int t[],c[];
int s=;
int e=head[root];
while(e)
{
int v=vet[e];
rep(i,,n) A[i]=;
Size=;
dfsD(v,root);
dfsU(v,root);
if(Size!=block) return ;
s++;
if(s==)
{
sort(A+,A+n+);
rep(i,,n) c[i]=A[i];
}
else
{
sort(A+,A+n+);
rep(i,,n)
if(A[i]!=c[i]) return ;
}
e=nxt[e];
}
return ;
} int main()
{
VI r;
srand();
prepare();
n=read();
rep(i,,n) head[i]=d[i]=;
tot=;
rep(i,,n-)
{
int x=read(),y=read();
add(x,y);
add(y,x);
d[x]++; d[y]++;
}
dfs1(,); r.clear(); rep(i,,n)
if(d[i]>=&&max(mx[i],n-sz[i])<=n/) r.pb(i); int ans=;
for(int i=;i<r.size();i++)
{
root=r[i];
if(isok(r[i],mx[r[i]])) ans=max(ans,d[r[i]]);
}
if(ans==) printf("-1\n");
else printf("%d\n",ans);
return ;
}

【CF1252F】Regular Forestation(重心,树同构)的更多相关文章

  1. Regular Forestation CodeForces - 1252F(树同构)

    Regular Forestation \[ Time Limit: 1000 ms\quad Memory Limit: 262144 kB \] 题意 给出一个节点为 \(n\) 的树,问删掉树上 ...

  2. uva12489 Combating cancer(树同构)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud https://uva.onlinejudge.org/index.php?opt ...

  3. Bzoj3197/洛谷3296 [SDOI2013]刺客信条assassin(树的重心+树Hash+树形DP+KM)

    题面 Bzoj 洛谷 题解 (除了代码均摘自喻队的博客,可是他退役了) 首先固定一棵树,枚举另一棵树,显然另一棵树只有与这棵树同构才有可能产生贡献 如果固定的树以重心为根,那么另一棵树最多就只有重心为 ...

  4. BZOJ4337: BJOI2015 树的同构(hash 树同构)

    题意 题目链接 Sol 树的同构问题,直接拿hash判一下,具体流程大概是这样的: 首先转化为有根树,预处理出第\(i\)棵树以\(j\)为根时的hash值. 那么两个树同构当且仅当把两棵树的hash ...

  5. Luogu 5043 【模板】树同构([BJOI2015]树的同构)

    BZOJ 4337 简单记录一种树哈希的方法:以$x$为根的子树的哈希值为$\sum_{y \in son(x)}f_y*base_i$,$f_y$表示以$y$为根的树的哈希值,其中$i$表示$f_y ...

  6. 『Andrew and Chemistry 树同构』

    Andrew and Chemistry Description During the chemistry lesson Andrew learned that the saturated hydro ...

  7. luogu P5043 【模板】树同构 hash 最小表示法

    LINK:模板 树同构 题目说的很迷 给了一棵有根树 但是重新标号 言外之意还是一棵无根树 然后要求判断是否重构. 由于时无根的 所以一个比较显然的想法暴力枚举根. 然后做树hash或者树的最小表示法 ...

  8. 【BZOJ3162】独钓寒江雪 树同构+DP

    [BZOJ3162]独钓寒江雪 题解:先进行树hash,方法是找重心,如果重心有两个,则新建一个虚点将两个重心连起来,新点即为新树的重心.将重心当做根进行hash,hash函数不能太简单,我的方法是: ...

  9. 【BZOJ3197】[Sdoi2013]assassin 树同构+动态规划+KM

    [BZOJ3197][Sdoi2013]assassin Description Input Output Sample Input 4 1 2 2 3 3 4 0 0 1 1 1 0 0 0 Sam ...

随机推荐

  1. idea的掌握

    1:idea的界面了解(一般都会勾选这两项,编码比较方便) 2: 如何配置sdk(jdk,最后一个生成的是.class文件的位置) 3: 如何单个项目配置和全局配置 4:如何配置项目的jdk编译版本和 ...

  2. PIL实现图片框架以及生成图片验证码

    1. PIL的基本概念 PIL:即Python Imaging Library,是Python平台事实上的图像处理标准库. PIL中涉及通道(bands)和模式(mode)这两个重要概念. (1)通道 ...

  3. 学习总结&实验报告1

    Java实验报告 1.打印输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其中各位数字立方和等于该数本身.例如,153是一个“水仙花数”. 实验代码: public class Project ...

  4. Js AJAX Event

    ;(function () { if ( typeof window.CustomEvent === "function" ) return false; function Cus ...

  5. go net库

    1 使用Listen函数创建一个server ln, err := net.Listen("tcp", ":8080") if err != nil { // ...

  6. 为什么 Java 线程没有 Running 状态?

    Java虚拟机层面所暴露给我们的状态,与操作系统底层的线程状态是两个不同层面的事.具体而言,这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态: 什么 ...

  7. java基础笔记(7)

    Socket编程 通信基础:ip地址(位置).协议(语言).端口(软件程序): java提供网络功能的四大类: InetAddress没有构造函数,不够里面有一些方法是可以返回实例,如: InetAd ...

  8. 08: mysql主从原理

    1.1 mysql主从同步   参考博客:https://www.cnblogs.com/kevingrace/p/6256603.html 1.mysql主从同步(复制)概念 1. 将Mysql某一 ...

  9. 关系型数据库为什么喜欢使用B+树作为索引结构? (转)

    问题1. 数据库为什么要设计索引? 图书馆存了1000W本图书,要从中找到<架构师之路>,一本本查,要查到什么时候去? 于是,图书管理员设计了一套规则: (1)一楼放历史类,二楼放文学类, ...

  10. Linux下查看日志用到的常用命令

    杀僵尸进程 部分程序员,肯定喜欢下面命令: ps -ef | grep java (先查java进程ID) kill -9  PID(生产环境谨慎使用) kill.killall.pkill命令的区别 ...