[2019 cattle off more school fourth] [G. Tree]

Topic links: https://ac.nowcoder.com/acm/contest/884/G

Title effect: Given a tree \ (A \), then give \ (T \) interrogation times, and asked \ (A \) how many there are connected subgraph tree \ (B_i \) isomorphism. \ (| A | \ leq 2000, t \ leq 10000, | B_i | \ leq 12 \)

Solution: This problem is actually Codeforces enhanced version of the 762F, and explanations on this question , please stamp here

   This question is similar to the approach this question before, but also after pretreatment tree DP minimum representation of a tree, but because there are as many as ten thousand times to ask, so consider pre-enumeration of all points of no more than \ (12 \) trees and find their minimal representation. How to satisfy all the conditions for pretreatment of trees, my method is assumed that the size of the current tree \ (n-\), the first \ (n + 1 \) as the point the current point or an ancestor thereof son added the tree, and continues recursively until the tree reaches a size \ (12 \). After such pretreatment will find the number of points does not exceed \ (12 \) tree less than \ (8000 \) months. The next step is to tree \ (A \) for DP, set f [i] [j] indicates the number to \ (I \) is the root node of the subtree with the number \ (J \) isomorphic tree, then make \ (ans [j] = \ sum_ {i = 1} ^ {n} f [i] [j] \), for the answer to each challenge is \ (\ sum ans [j] \), where \ (J \) tree \ corresponding to different points when the root number (B \).

   In addition, at the time of the pretreatment, we can also pre-out when the number \ (j \) in the root of the tree as the number of new trees after the number \ (i \) is the son of the root of the tree merge, such The combined relationship is less than \ (14,000 \) group. Enumeration can be carried out by DP tree \ (A \) all such combined relationship is calculated, the time complexity of this part of the optimization \ (O (14000n) \)

#include<bits/stdc++.h>
using namespace std;
#define N 2001
#define M 1<<12
#define MM 8001 
#define NN 16773121
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
int cnt;
set<int>id[13];
int uni[MM][MM];
int num_to_id[NN];
int id_to_num[MM];
int f[N][MM];
vector<int>Id[13];
struct Tree
{
    int sz[N];
    int n,ans[NN];
    vector<int>d[N];
    vector<int>mp[MM];
    void read()
      {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        d[i].clear();
      for(int i=2;i<=n;i++)
        {
        int u,v;
        scanf("%d%d",&u,&v);
        d[u].push_back(v);
        d[v].push_back(u);
        }
      }
    int dfs(int cur,int pre)
      {
      sz[cur]=1;
      int res=1;
      vector<int>tmp;
      for(auto nxt:d[cur])if(nxt!=pre)
        tmp.push_back(dfs(nxt,cur)),sz[cur]+=sz[nxt];
      sort(tmp.begin(),tmp.end());
      for(auto x:tmp)res=Union(res,x);
      res<<=1;
      if(!num_to_id[res])cnt++,mp[cnt]=tmp,id_to_num[cnt]=res,num_to_id[res]=cnt;
      for(int i=0;i<tmp.size();i++)
        {
        int R=1;
        for(int j=0;j<tmp.size();j++)if(j!=i)
          R=Union(R,tmp[j]);
        R<<=1;
        uni[num_to_id[R]][num_to_id[tmp[i]]]=num_to_id[res];
        }
      id[sz[cur]].insert(num_to_id[res]);
      return res;
      }
    void getID()
      {
      for(int i=1;i<=n;i++)
        dfs(i,0);
      }
    void DP2(int cur,int pre)
      {
      sz[cur]=1;
      f[cur][1]=1;
      for(auto nxt:d[cur])if(nxt!=pre)
        {
        DP2(nxt,cur);
        for(int i=min(12,sz[cur]);i>=1;i--)
          for(auto ii:Id[i])
            {
            int v=f[cur][ii];
            if(!v)continue;
            for(int j=1;j<=min(12-i,sz[nxt]);j++)
              for(auto jj:Id[j])
                (f[cur][uni[ii][jj]]+=v*f[nxt][jj]%MOD)%=MOD;
            }
        sz[cur]+=sz[nxt];
        }
      for(int i=1;i<=min(12,sz[cur]);i++)
        for(auto ii:Id[i])
          (ans[ii]+=f[cur][ii])%=MOD;
      }
}S,T;
set<int>s;
int fa[13];
vector<int>d[13];
void fuck(int cur,int pre)
{
    fa[cur]=pre;
    for(int i=1;i<=12;i++)
      T.d[i]=d[i];
    T.n=cur;
    if(cur==12){T.dfs(1,0);return;}
    int x=cur;
    while(x!=0)
      {
      d[x].push_back(cur+1);
      fuck(cur+1,x);
      d[x].pop_back();
      x=fa[x];
      }
}
int main()
{
    fuck(1,0);
    for(int i=1;i<=12;i++)
      for(auto j:id[i])Id[i].push_back(j);
    S.read();
    S.DP2(1,0);
    int t;
    scanf("%d",&t);
    while(t--)
      {
      T.read();
      int ans=0;
      s.clear();
      for(int i=1;i<=T.n;i++)
        s.insert(T.dfs(i,0));
      for(auto x:s)(ans+=S.ans[num_to_id[x]])%=MOD;
      printf("%d\n",ans);
      }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/DeaphetS/p/11260559.html