[树形DP 杂题] SRM 562 div1 InducedSubgraphs

来源:互联网 发布:如何做小吃生意知乎 编辑:程序博客网 时间:2024/05/22 13:11

集训队作业传送门

给一棵n个结点的树,定义一个结点集合是连通的表示这棵树以这个集合为点集的导出子图是连通图。再给一个整数k,将树上的结点重新编号,使得对于任意一个满足1ink+1i,都满足由所有编号在[i,i+k1]内的结点组成的结点集合是连通的。问这样的编号方式有多少种。1kn41

大概是分两种情况讨论 详见题解

这里写图片描述

中间一条链 两边两棵子树 父亲比儿子大或小 直接用组合数DP下

这里写图片描述

考虑把白点中最小点提到根 然后gi,j,k表示子树 i 中有 j 个蓝点 k 个红点

// BEGIN CUT HERE  #include<conio.h>#include<sstream>// END CUT HERE  #include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<string>#include<set>#define cl(x) memset(x,0,sizeof(x))using namespace std;typedef long long ll;const int N=55;const int P=1e9+9;ll C[N][N],fac[N];inline void Pre(int n){  fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%P;  C[0][0]=1;  for (int i=1;i<=n;i++){    C[i][0]=1;    for (int j=1;j<=i;j++)      C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;  }}struct edge{  int u,v,next;}G[N<<1];int head[N],inum;inline void add(int u,int v,int p){  G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;}#define V G[p].vint n,m,K;int fat[N],depth[N],size[N];inline void _dfs(int u,int fa){  depth[u]=depth[fa]+1; fat[u]=fa;  for (int p=head[u];p;p=G[p].next)    if (V!=fa)      _dfs(V,u);}int vst[N]; ll f[N];inline void dfs(int u,int fa){  size[u]=1;  for (int p=head[u];p;p=G[p].next)    if (V!=fa && !vst[V])      dfs(V,u),size[u]+=size[V];  int tot=size[u]-1; f[u]=1;  for (int p=head[u];p;p=G[p].next)    if (V!=fa && !vst[V]){      f[u]=f[u]*f[V]%P*C[tot][size[V]]%P;      tot-=size[V];    }}inline int Solve1(){  ll ans=0;  for (int i=1;i<=n;i++)    for (int j=1;j<=n;j++){      if (i==j) continue;      _dfs(i,0);      if (depth[j]==n-2*K+2){    for (int k=1;k<=n;k++) vst[k]=0;    for (int k=j;k!=i;k=fat[k]) vst[k]=1; vst[i]=1;    dfs(i,0); dfs(j,0);    if (size[i]==K && size[j]==K)      ans+=f[i]*f[j]%P;      }    }  return ans%P;}ll g[N][N][N];inline void dp(int u,int fa){  g[u][0][0]=1; size[u]=1;  for (int p=head[u];p;p=G[p].next)    if (V!=fa){      dp(V,u); size[u]+=size[V];      for (int i=m;~i;i--)    for (int j=m;~j;j--){      if (!g[u][i][j]) continue;        for (int a=0;a+i<=m;a++)          for (int b=0;b+j<=m;b++){          if (!a && !b) continue;            if (!g[V][a][b]) continue;            (g[u][i+a][j+b]+=g[u][i][j]*g[V][a][b]%P*C[i+a][i]%P*C[j+b][j]%P)%=P;        }    }    }  if (size[u]<=m){    dfs(u,fa);    (g[u][size[u]][0]+=f[u])%=P;    (g[u][0][size[u]]+=f[u])%=P;  }}inline int Solve2(){  ll ans=0;  m=n-K;  for (int i=1;i<=n;i++){    cl(g);    dp(i,0);    ans+=g[i][m][m];  }  return ans%P*fac[2*K-n-1]%P;}class InducedSubgraphs{public:  int getCount(vector <int> edge1, vector <int> edge2, int k){    n=edge1.size()+1; K=k; cl(head); inum=0;    for (int i=0;i<(int)edge1.size();i++)      add(edge1[i]+1,edge2[i]+1,++inum),add(edge2[i]+1,edge1[i]+1,++inum);    Pre(n);    if (K==1 || K==n) return fac[n];    if (2*K<=n)      return Solve1();    else      return Solve2();  }  // BEGIN CUT HEREpublic:  void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); if ((Case == -1) || (Case == 5)) test_case_5(); if ((Case == -1) || (Case == 6)) test_case_6(); }private:  template <typename T> string print_array(const vector<T> &_V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = _V.begin(); iter != _V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }  void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }  void test_case_0() { int Arr0[] = {0, 1}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {1, 2}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 2; int Arg3 = 2; verify_case(0, Arg3, getCount(Arg0, Arg1, Arg2)); }  void test_case_1() { int Arr0[] = {0, 1, 3}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {2, 2, 2}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 3; int Arg3 = 12; verify_case(1, Arg3, getCount(Arg0, Arg1, Arg2)); }  void test_case_2() { int Arr0[] = {5, 0, 1, 2, 2}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 1, 2, 4, 3}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 3; int Arg3 = 4; verify_case(2, Arg3, getCount(Arg0, Arg1, Arg2)); }  void test_case_3() { int Arr0[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 11; int Arg3 = 481904640; verify_case(3, Arg3, getCount(Arg0, Arg1, Arg2)); }  void test_case_4() { int Arr0[] = {5, 9, 4, 10, 10, 0, 7, 6, 2, 1, 11, 8}    ; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 0, 10, 3, 0, 6, 1, 1, 12, 12, 7, 11}    ; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 6; int Arg3 = 800; verify_case(4, Arg3, getCount(Arg0, Arg1, Arg2)); }  void test_case_5() { int Arr0[] = {0, 5, 1, 0, 2, 3, 5}    ; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {4, 7, 0, 6, 7, 5, 0}    ; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 3; int Arg3 = 0; verify_case(5, Arg3, getCount(Arg0, Arg1, Arg2)); }  void test_case_6() { int Arr0[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 1; int Arg3 = 890964601; verify_case(6, Arg3, getCount(Arg0, Arg1, Arg2)); }  // END CUT HERE};// BEGIN CUT HEREint main(){  InducedSubgraphs ___test;  ___test.run_test(-1);  getch() ;  return 0;}// END CUT HERE
0 0
原创粉丝点击