题意:给定一棵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. 20191110 Spring Boot官方文档学习(4.2)

    4.2.外部化配置 Spring Boot使您可以外部化配置,以便可以在不同环境中使用相同的应用程序代码.您可以使用Properties文件,YAML文件,环境变量和命令行参数来外部化配置.属性值可以 ...

  2. input输入框的的input事件和change事件以及change和blur事件的区别

    input输入框的 oninput事件 ,在用户输入的时候触发,只要元素值发生变化就会触发 input输入框的 onchange事件 ,要在输入框失去焦点的时候触发事件,当鼠标在其他地方点击一下才会触 ...

  3. 分享一个linux系统中循环遍历两个数组内容,并输出数组中的不同内容的shell脚本

    cat diffarray.sh #!/bin/bash arry_list1=(1 2 3 4 5 6 7 8 9) arry_list2=(3 5 8) declare -a diff_list ...

  4. 关于java范型

    1 范型只在编译阶段有效 编译器在编译阶段检查范型结果之后,就会将范型信息删除.范型信息不会进入运行时阶段. 泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型. 2 不能对确定的范型 ...

  5. Spark启动流程(Standalone)- master源码

    Master源码 package org.apache.spark.deploy.master //伴生类 private[deploy] class Master( override val rpc ...

  6. Maven项目的常用jar包

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  7. mysql数据库问题———登录进去无法操作显示You must reset your password using ALTER USER statement before executing this statement

    linux操作mysql数据库,可以登陆进去,但是操作所有命令都显示You must reset your password using ALTER USER statement before exe ...

  8. stringstream istringstream ostringstream 三者的区别

    stringstream istringstream ostringstream 三者的区别 说明 ostringstream : 用于执行C风格字符串的输出操作. istringstream : 用 ...

  9. Codeforces 1255F Point Ordering(凸包+叉积)

    我们随机选取点1,2作为凸包的一个分割线,那么我们可以直接枚举剩下n-2个点找到他们和向量1-2的叉积大小与正负,然后我们可以根据叉积的正负,先将他们分割出两个区域,在向量1-2的下方还是上方,接下来 ...

  10. java int转Short

    使用short(xx) problemMultipleChoiceDO.setExamCount((short)0);//在数据库中是smallint类型