题目大意: 给你一棵树,让你切断一些边,使得剩下的每个连通块的点的个数的乘积最大,输出这个乘积。
题目分析: 由于题目要求各个连通块点的乘积,设状态dp[i][j]表示i作为一个连通块时其点个数为j时候的值。每次枚举与当前节点联通的其他节点所已经扩展的总结点数量。则dp[u][i+j]=max(dp[u][i]*dp[v][j]) {其中u为当前节点,v为u的子节点,i,j分别枚举u和v的联通块的点的个数。}
再加上高精压四位处理就ac了。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #include<cmath> #include<cctype> #include<cassert> #include<climits> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,n) for(int i=n;i;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define RepD(i,n) for(int i=n;i>=0;i--) #define MEM(a) memset(a,0,sizeof(a)) #define MEMI(a) memset(a,127,sizeof(a)) #define MEMi(a) memset(a,128,sizeof(a)) #define INF (2139062143) #define phiF (1000000006) #define MAXN (1000000+10) typedef long long LL; const int mod = 10000; int num[2005],first[2005],n,u,v,tot; struct info{ int to,next; }e[2005]; void add(int x,int y){ tot++; e[tot].to=y; e[tot].next=first[x]; first[x]=tot; } struct tar{ int a[80],n; tar(){}; tar(int x) { MEM(a); n = 1, a[0] = x; } void init(int x) { n = 1, a[0] = x; } bool operator < (const tar &x) { if (n < x.n) return 1; else if (n > x.n) return 0; RepD(i,n-1) if (a[i] < x.a[i]) return 1; else if (a[i] > x.a[i]) return 0; return 0; } tar operator * (const tar &x) { tar t(0); t.n = x.n + n - 1; Rep(i,n) Rep(j,x.n) t.a[i + j] += a[i] * x.a[j]; Rep(i,t.n) { t.a[i + 1] += t.a[i] / mod; t.a[i] %= mod; } if (t.a[t.n]) t.n++; return t; } tar operator + (const tar x) { tar t(0); t.n = max(x.n, n); Rep(i,t.n) { t.a[i] = t.a[i] + x.a[i] + a[i]; t.a[i + 1] += t.a[i] / mod; t.a[i] %= mod; } if (t.a[t.n]) ++t.n; return t; } void print() { printf("%d", a[n - 1]); RepD(i,n-2) printf("%04d", a[i]); puts(" "); } }dp[705][705]; void dfs(int u,int fa){ num[u]=1; dp[u][0]=(0); dp[u][1]=(1); for (int p=first[u];p;p=e[p].next){ int v=e[p].to; if (v==fa) continue ; dfs(v,u); RepD(i,num[u]) RepD(j,num[v]){ tar tmp=dp[u][i]*dp[v][j]; if (dp[u][i+j]<tmp) dp[u][i+j]=tmp; } num[u]+=num[v]; } For (i,num[u]){ tar tmp(i); tmp=tmp*dp[u][i]; if (dp[u][0]<tmp) dp[u][0]=tmp; } } int main(){ scanf("%d",&n); For (i,n-1){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1,0); dp[1][0].print(); }