272. 【NOIP2015模拟10.28B组】序章-弗兰德的秘密
(File IO): input:frand.in output:frand.out
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Goto ProblemSet做法::树型 DP。设状态 F[x][y]表示,第一棵树中 x 节点与第二 棵树中的 y 节点作为根节点匹配的最大同构。例如,上图中所示的 F[x][y] = 3 。 现在转移方程就很显然了: F[x][y] = Max { F[x 的儿子][y 的儿子] } + 1 ; 这里需要枚举 x 的那些儿子与 y 的哪些儿子匹配,这部分时间复 杂度 O( 5! ) ; 最后答案就是 F[1][1]。
代码如下:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define rep(i,a,b) for(int i=a;i<=b;i++) 5 #define N 1007 6 using namespace std; 7 int f[N][N], n, m, sn[N][N], sm[N][N], ans, q, p; 8 bool bj[N]; 9 10 int max(int a, int b) { if (a > b) return a; return b; } 11 12 void find(int t, int same) 13 { 14 if (t == sn[q][0] + 1) 15 { 16 f[q][p] = max(f[q][p], same); 17 return; 18 } 19 find(t + 1, same); 20 bool b = 0; 21 rep(i, 1, sm[p][0]) 22 { 23 if (bj[i]) continue; 24 b = 1; 25 bj[i] = 1; 26 find(t + 1, same + f[sn[q][t]][sm[p][i]]); 27 bj[i] = 0; 28 } 29 if (!b) 30 { 31 f[q][p] = max(f[q][p], same); 32 } 33 } 34 35 void work(int x) 36 { 37 if (sn[x][0] == 0) 38 { 39 rep(i, 1, m) 40 f[x][i] = 1; 41 return; 42 } 43 rep(i, 1, sn[x][0]) work(sn[x][i]); 44 rep(i, 1, m) 45 { 46 if (sm[i][0] == 0) 47 { 48 f[x][i] = 1; 49 continue; 50 } 51 q = x; 52 p = i; 53 find(1, 0); 54 f[q][p]++; 55 if (x == 1 && i == 1) ans = max(f[q][p], ans); 56 } 57 } 58 59 int main() 60 { 61 freopen("frand.in", "r", stdin); 62 freopen("frand.out", "w", stdout); 63 scanf("%d%d", &n, &m); 64 rep(i, 1, n - 1) 65 { 66 scanf("%d%d", &q, &p); 67 sn[q][++sn[q][0]] = p; 68 } 69 rep(i, 1, m - 1) 70 { 71 scanf("%d%d", &q, &p); 72 sm[q][++sm[q][0]] = p; 73 } 74 work(1); 75 printf("%d", ans); 76 fclose(stdin); 77 fclose(stdout); 78 return 0; 79 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步