【CF1252F】Regular Forestation(重心,树同构)

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

n<=4000

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

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

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef long double ld;
  7 typedef pair<int,int> PII;
  8 typedef pair<ll,ll> Pll;
  9 typedef vector<int> VI;
 10 typedef vector<PII> VII;
 11 typedef pair<ll,ll>P;
 12 #define N  200010
 13 #define M  1000000
 14 #define INF 1e9
 15 #define fi first
 16 #define se second
 17 #define MP make_pair
 18 #define pb push_back
 19 #define pi acos(-1)
 20 #define mem(a,b) memset(a,b,sizeof(a))
 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 23 #define lowbit(x) x&(-x)
 24 #define Rand (rand()*(1<<16)+rand())
 25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 26 #define ls p<<1
 27 #define rs p<<1|1
 28 #define fors(i) for(auto i:e[x]) if(i!=p)
 29 
 30 const int MOD=1e9+7,inv2=(MOD+1)/2;
 31       double eps=1e-6;
 32       int dx[4]={-1,1,0,0};
 33       int dy[4]={0,0,-1,1};
 34 
 35 int head[N],vet[N],nxt[N],sz[N],mx[N],d[N],tot,Size,root;
 36 
 37 int read()
 38 {
 39    int v=0,f=1;
 40    char c=getchar();
 41    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 42    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 43    return v*f;
 44 }
 45 
 46 ll readll()
 47 {
 48    ll v=0,f=1;
 49    char c=getchar();
 50    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 51    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 52    return v*f;
 53 }
 54 
 55 void add(int a,int b)
 56 {
 57     nxt[++tot]=head[a];
 58     vet[tot]=b;
 59     head[a]=tot;
 60 }
 61 
 62 void dfs1(int u,int fa)
 63 {
 64     int e=head[u];
 65     sz[u]=1,mx[u]=0;
 66     while(e)
 67     {
 68         int v=vet[e];
 69         if(v!=fa)
 70         {
 71             dfs1(v,u);
 72             sz[u]+=sz[v];
 73             mx[u]=max(mx[u],sz[v]);
 74         }
 75         e=nxt[e];
 76     }
 77 }
 78 
 79 int ra[N];
 80 
 81 int pw(int x,int y)
 82 {
 83     int res=1;
 84     while(y)
 85     {
 86         if(y&1) res=1ll*res*x%MOD;
 87         x=1ll*x*x%MOD;
 88         y>>=1;
 89     }
 90     return res;
 91 }
 92 
 93 int inv(int x)
 94 {
 95     return pw(x,MOD-2);
 96 }
 97 
 98 struct Sub
 99 {
100     VI S;
101     int d1,d2,H1,H2;
102     Sub(){d1=d2=0; S.clear();}
103 
104     void add(int d,int v)
105     {
106         S.pb(v);
107         if(d>d1) d2=d1,d1=d;
108          else if(d>d2) d2=d;
109     }
110 
111     int Hash()
112     {
113         H1=H2=1;
114         for(int i:S)
115         {
116             H1=1ll*H1*(ra[d1]+i)%MOD;
117             H2=1ll*H2*(ra[d2]+i)%MOD;
118         }
119         return H1;
120     }
121 
122     PII del(int d,int v)
123     {
124         if(d==d1) return {d2+1,1ll*H2*inv(ra[d2]+v)%MOD};
125         return {d1+1,1ll*H1*inv(ra[d1]+v)%MOD};
126     }
127 };
128 
129 PII U[N];
130 int n,i,x,y,A[N];
131 Sub T[N];
132 
133 void prepare(int n)
134 {
135     rep(i,0,n) ra[i]=rand()%MOD;
136 }
137 
138 void dfsD(int u,int p)
139 {
140     Size++;
141     T[u]=Sub();
142     int e=head[u];
143     while(e)
144     {
145         int v=vet[e];
146         if(v!=p)
147         {
148             dfsD(v,u);
149             T[u].add(T[v].d1+1,T[v].H1);
150         }
151         e=nxt[e];
152     }
153     T[u].Hash();
154 }
155 
156 void dfsU(int u,int p)
157 {
158     if(p!=root) T[u].add(U[u].fi,U[u].se);
159     A[u]=T[u].Hash();
160     int e=head[u];
161     while(e)
162     {
163         int v=vet[e];
164         if(v!=p)
165         {
166             U[v]=T[u].del(T[v].d1+1,T[v].H1);
167             dfsU(v,u);
168         }
169         e=nxt[e];
170     }
171 }
172 
173 int isok(int root,int block)
174 {
175     int t[5000],c[5000];
176     int s=0;
177     int e=head[root];
178     while(e)
179     {
180         int v=vet[e];
181         rep(i,1,n) A[i]=0;
182         Size=0;
183         dfsD(v,root);
184         dfsU(v,root);
185         if(Size!=block) return 0;
186         s++;
187         if(s==1)
188         {
189             sort(A+1,A+n+1);
190             rep(i,1,n) c[i]=A[i];
191         }
192          else
193          {
194              sort(A+1,A+n+1);
195              rep(i,1,n)
196               if(A[i]!=c[i]) return 0;
197          }
198         e=nxt[e];
199     }
200     return 1;
201 }
202 
203 int main()
204 {
205     VI r;
206     srand(23333);
207     prepare(5000);
208     n=read();
209     rep(i,1,n) head[i]=d[i]=0;
210     tot=0;
211     rep(i,1,n-1)
212     {
213         int x=read(),y=read();
214         add(x,y);
215         add(y,x);
216         d[x]++; d[y]++;
217     }
218     dfs1(1,0);
219 
220     r.clear();
221 
222     rep(i,1,n)
223      if(d[i]>=2&&max(mx[i],n-sz[i])<=n/2) r.pb(i);
224 
225 
226     int ans=0;
227     for(int i=0;i<r.size();i++)
228     {
229         root=r[i];
230         if(isok(r[i],mx[r[i]])) ans=max(ans,d[r[i]]);
231     }
232     if(ans==0) printf("-1\n");
233      else printf("%d\n",ans);
234     return 0;
235 }

猜你喜欢

转载自www.cnblogs.com/myx12345/p/11801773.html