題目大意:給你一棵樹,讓你切斷一些邊,使得剩下的每個連通塊的點的個數的乘積最大,輸出這個乘積。
題目分析: 由於題目要求各個連通塊點的乘積,設狀態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(); }
Codeforces 23 E Tree 樹形dp+高精
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.