【cf23E】Tree
2016-07-19 20:59
381 查看
link to problem
【题目大意】
给出一棵树,求一个对树的划分方法使得每棵子树大小的乘积最大。
【题解】树上背包dp
一看到题目的时候想的是贪心(?是可以的然而我太菜了不会?),因为曾经有一道题是拆分序列为2和3的什么什么的。。。= =扯远了
{状态设计} f[i][j] 表示以 i 为根的子树中与 i 的父亲相连的有 j 个节点时,这棵子树的乘积最大值,故最终答案ans=f[1][0];
{转移方程} f[i][j+k]=max(f[i][j]*f[son[i]][k]),其中 j<=size[i], k<=size[son[i]];
【呆马初级版(⊙_⊙)】
【题外话】
真的以为这就结束了吗,其实还要加高精呢(⊙o⊙)!
然后就随便加了个重载然后???炸了???
//当初真的是手贱押位的时候没搞好生生卡一波……
【AC呆马+高精】
【题目大意】
给出一棵树,求一个对树的划分方法使得每棵子树大小的乘积最大。
【题解】树上背包dp
一看到题目的时候想的是贪心(?是可以的然而我太菜了不会?),因为曾经有一道题是拆分序列为2和3的什么什么的。。。= =扯远了
{状态设计} f[i][j] 表示以 i 为根的子树中与 i 的父亲相连的有 j 个节点时,这棵子树的乘积最大值,故最终答案ans=f[1][0];
{转移方程} f[i][j+k]=max(f[i][j]*f[son[i]][k]),其中 j<=size[i], k<=size[son[i]];
【呆马初级版(⊙_⊙)】
#include <cstdio> #include <cstring> struct edge{ int to,nxt;}e[2000]; int n,cnt,s[1000],fi[1000],ans,f[705][705]; void add(int u,int v) { e[++cnt].to=v;e[cnt].nxt=fi[u];fi[u]=cnt; } void dp(int x,int fa) { s[x]=1;f[x][1]=1; for (int i=fi[x];i;i=e[i].nxt) if (e[i].to!=fa) { dp(e[i].to,x); for (int j=s[x];j>=0;--j) for (int k=s[e[i].to];k>=0;--k) f[x][j+k]=max(f[x][j]*f[e[i].to][k],f[x][j+k]); s[x]+=s[e[i].to]; } for (int i=1;i<=s[x];++i) f[x][0]=max(f[x][0],f[x][i]*i); } int main() { scanf("%d\n",&n); for (int i=1;i<n;++i) { int u,v; scanf("%d%d\n",&u,&v); add(u,v);add(v,u); } dp(1,0);ans=f[1][0]; printf("%d\n",ans); return 0; }
【题外话】
真的以为这就结束了吗,其实还要加高精呢(⊙o⊙)!
然后就随便加了个重载然后???炸了???
//当初真的是手贱押位的时候没搞好生生卡一波……
【AC呆马+高精】
#include <cstdio> #include <cstring> #define bit 10000 struct edge{ int to,nxt;}e[2000]; struct number{ int a[100];}ans,f[705][705]; int n,cnt,s[1000],fi[1000]; number operator*(number x,number y) { number z; memset(z.a,0,sizeof(z.a)); for (int i=1;i<=x.a[0];++i) for (int j=1;j<=y.a[0];++j) z.a[i+j-1]+=x.a[i]*y.a[j]; z.a[0]=x.a[0]+y.a[0]-1; for (int i=1;i<=z.a[0];++i) { z.a[i+1]+=z.a[i]/bit; z.a[i]%=bit; } if (z.a[z.a[0]+1]) ++z.a[0]; return z; } number max(number x,number y) { if (x.a[0]>y.a[0]) return x; if (x.a[0]<y.a[0]) return y; for (int i=x.a[0];i;--i) if (x.a[i]>y.a[i]) return x; else if (x.a[i]<y.a[i]) return y; return x; } number change(int x){ number a;a.a[0]=1;a.a[1]=x;return a;} void add(int u,int v) { e[++cnt].to=v;e[cnt].nxt=fi[u];fi[u]=cnt; } void dp(int x,int fa) { s[x]=1;f[x][1].a[0]=f[x][1].a[1]=1; for (int i=fi[x];i;i=e[i].nxt) if (e[i].to!=fa) { dp(e[i].to,x); for (int j=s[x];j>=0;--j) for (int k=s[e[i].to];k>=0;--k) f[x][j+k]=max(f[x][j]*f[e[i].to][k],f[x][j+k]); s[x]+=s[e[i].to]; } f[x][0]=change(s[x]); for (int i=1;i<=s[x];++i) f[x][0]=max(f[x][0],f[x][i]*change(i)); } void print(number x) { printf("%d",x.a[x.a[0]]); for (int i=x.a[0]-1;i;--i) printf("%.4d",x.a[i]); } int main() { scanf("%d\n",&n); for (int i=1;i<n;++i) { int u,v; scanf("%d%d\n",&u,&v); add(u,v);add(v,u); } dp(1,0);ans=f[1][0]; print(ans); return 0; }
相关文章推荐
- 树形DP 或 最小顶点覆盖=最大匹配(双向图)(HDU 1053)
- [BZOJ1017][JSOI2008][树形DP]魔兽地图DotR
- ZOJ3824 Fiber-optic Network
- [字符串]FJSDFZOJ 1134 整数去位
- hihocoder #1035 : 自驾旅行 III 树形DP
- vijos 1892 树上的最大匹配问题 树形dp
- Codeforces 23 E Tree 树形dp+高精
- Codeforces 543 D Road Improvement 树形dp
- Codeforces 161 D Distance in Tree 树形DP
- 贴一个高精加= =纪念某道有毒的题
- POJ 3342
- URAL1018
- hdu1561 zoj3201
- poj 3107 Godfather
- zoj3201Tree of Tree
- Codeforces Round #135 (Div. 2)VD. Choosing Capital for Treeland
- POJ 1848 Tree
- HDU 1561 The more, The Better(树形DP)
- UVALive 6436 The Busiest City
- 树形dp简单总结