Codeforces 23 E Tree 樹形dp+高精

題目大意:給你一棵樹,讓你切斷一些邊,使得剩下的每個連通塊的點的個數的乘積最大,輸出這個乘積。



題目分析: 由於題目要求各個連通塊點的乘積,設狀態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();
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章