题意:给定一棵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. 重载Prometheus配置

    发送SIGHUP信号给应用程序的主进程: pid ‘’-1‘’是指“终端断线” 发送post请求给指定端点: curl -XPOST http://ip:9090/-/reload 对于此种方法要注意 ...

  2. 使用CyclicBarrier+线程池,按总页数分批次开多线程执行逻辑

    通过CyclicBarrier+线程池的方式,同步的方式分页分批次并发高效处理逻辑,将总页数分成多个批次并发执行每页逻辑,每个批次处理DO_MAX_SIZE个页,每个批次等待DO_MAX_SIZE个页 ...

  3. Linux环境安装mongodb

    介绍 上篇介绍了Linux环境下安装Node.js的步骤,紧接着来安装mongodb.另外,推荐我的另一篇 Windows下图文详解Mongodb安装及配置,先在Windows下熟悉下mongodb, ...

  4. P1219八皇后

    这个题是一道USACO的经典dfs,与我见面的时间起码七个月了. 放置n个皇后于n*n棋盘,他们不能互相吃(行,列,对角线),问有几种摆法?于是想到了dfs(自我认为有图的就不用DP).首先确定好了要 ...

  5. python文件打包/导入 .so 文件

    打包so文件 见: http://www.cnblogs.com/ke10/p/py2so.html 导入so文件 import sys sys.path.append(r'/home/project ...

  6. js中箭头函数 及 针对箭头函数this指向问题引出的单体模式

    ES6允许使用“箭头”(=>)定义函数 var f = a = > a //等同于 var f = function(a){ return a; } 如果箭头函数不需要参数或需要多个参数, ...

  7. Java中的sort

    Java中对集合排序有两种方式 Comparable和Comparator public static <T> void sort(List<T> list); 将集合中的数据 ...

  8. Java关于继承中的内存分配

    1.定义         super:当前对象的父类对象         this   :当前对象,谁调用this所在的方法,this就是哪一个对象.   2.内存分析 另一个例子: public s ...

  9. 从零开始配置安装Flutter开发环境

    flutter 中文网 https://flutterchina.club/get-started/install/ 1.配置全局环境 PUB_HOSTED_URL=https://pub.flutt ...

  10. php设置错误级别

    ini_set('display_errors', 1); error_reporting(E_ALL);