[树形DP 杂题] SRM 562 div1 InducedSubgraphs
来源:互联网 发布:如何做小吃生意知乎 编辑:程序博客网 时间:2024/05/22 13:11
集训队作业传送门
给一棵
大概是分两种情况讨论 详见题解
中间一条链 两边两棵子树 父亲比儿子大或小 直接用组合数DP下
考虑把白点中最小点提到根 然后
// 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
- [树形DP 杂题] SRM 562 div1 InducedSubgraphs
- SRM 719 div1 Medium (树形dp)
- [DP套DP] SRM 591 div1 StringPath
- srm 556 div1 500 LeftRightDigitsGame2(DP)
- srm 181 div1 1000(状压dp)
- Topcoder SRM 662 Div1, ExactTree,DP
- SRM 562 Div1 500 CheckerFreeness
- SRM 584 div1 lev3(最小树形图)
- Topcoder SRM 651 div1 250 题解 (概率dp)
- TopCoder SRM 667 Div1 Problem 250 - OrderOfOperations (状压dp)
- Topcoder SRM 144 Div2 1100 (树形dp)
- topcoder SRM 666 DIV2 CollectingTokens 树形dp
- SRM 465(DIV1 DIV2)
- SRM 465(DIV1 DIV2)
- SRM 144 DIV1 second
- SRM 507 DIV1 B
- SRM 513 DIV1 C
- SRM 500 DIV1 B
- keil中常见的几种警告
- c语言实现二叉查找树
- 学习笔记整理——用户,属组以及密码相关
- Hibernate中英文查询成功中文查询失败
- git log 误删找回
- [树形DP 杂题] SRM 562 div1 InducedSubgraphs
- Atitit 数据融合merge功能v3新特性.docx
- Jsp使用Cookie完成记住账号密码的功能
- 单独启动tomcat正常,但是eclipse下不能正确启动tomcat问题的解决
- node.js学习总结
- 4D Result : iBET Power Station ticket Lucky Draw
- 【web前端】遇到的事儿之 regeneratorRuntime is not defined
- springmvc 防止重复提交
- 274. H-Index