luogu P1623 [CEOI2007]树的匹配Treasury
题目链接:
luogu P1623 [CEOI2007]树的匹配Treasury
题解:
设dp[u][0]表示在以u为根的子树中,u不匹配能得到的最大匹配数,dp[u][1]表示在以u为根的子树中,匹配u等得到的最大匹配数
显然dp[u][1]一定是>=dp[u][0]的,那么 \(dp[u][0]=max(dp[v][1])\)
那么\(dp[u][1]=\sum(max(dp[v][1],dp[u][0]+dp[v][0]+1))\)
对于计数,乘法原理搞一搞就好了
高精度
代码:
// luogu-judger-enable-o2
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::vector;
using std::max;
using std::min;
inline int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar() ;}
while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar() ;
return x*f;
}
const int maxn = 1007;
struct node{
int v,next;
}edge[maxn];
int dp[maxn][2],head[maxn],num=0;
inline void add_edge(int u,int v) {
edge[++num].v=v;edge[num].next=head[u];head[u]=num;
}
int n;
void init() {
n=read();
for(int num,k,i=1;i<=n;++i) {
k=read(),num=read();
for(int j=1;j<=num;++j)
add_edge(k,read());
}
}
struct Int {
static const int Bit=1e4;//压3位
int a[107],size;
inline void operator = (const int &x) {
memset(a,0,sizeof a) ;a[size=1]=x;
}
inline Int operator + (const Int t ) {
Int c=*this;
int sz =max(c.size,t.size);
for(int i=1;i<=sz;++i)
c.a[i]+=t.a[i],c.a[i+1]+=c.a[i]/Bit,c.a[i]%=Bit;
if(c.a[sz+1])sz++;
c.size=sz;
return c;
}
inline Int operator * (const Int t) {
int sz=size+t.size-1;
Int c;c=0;
for(int i=1;i<=size;++i)
for(int j=1;j<=t.size;++j)
c.a[i+j-1]+=a[i]*t.a[j];
for(int i=1;i<=sz;++i)
c.a[i+1]+=c.a[i]/Bit,c.a[i]%=Bit;
if(c.a[sz+1])sz++;c.size=sz;
return c;//XD
}
inline void print() {
printf("%d",a[size]);
for(int i=size-1;i;--i)
printf("%04d",a[i]);
}
}cnt[maxn][2];
inline void operator *= (Int &a,Int b) {a=a*b;}
inline void operator += (Int &a,Int b) {a=a+b;}
void dfs(int x) {
//int num = vec[x].size();
cnt[x][0]=1;cnt[x][1]=1;
for(int i=head[x];i;i=edge[i].next) {
int v=edge[i].v;
dfs(v);
if(dp[x][1]) {
dp[x][1]+=dp[v][1];
if(dp[v][0]!=dp[v][1]) cnt[x][1]*=cnt[v][1];
else cnt[x][1]*=cnt[v][0]+cnt[v][1];
}
if(dp[x][0]+dp[v][0]+1 > dp[x][1]) dp[x][1] = dp[x][0]+dp[v][0]+1,cnt[x][1]=cnt[x][0]*cnt[v][0];
else if(dp[x][0]+dp[v][0]+1 == dp[x][1]) cnt[x][1] += cnt[x][0]*cnt[v][0];
dp[x][0]+=dp[v][1];
if(dp[v][0]!=dp[v][1]) cnt[x][0]*=cnt[v][1];
else cnt[x][0]*=cnt[v][0]+cnt[v][1];
}
if(!dp[x][1]) cnt[x][1]=0;
}
int main() {
init();
dfs(1);
printf("%d\n",dp[1][1]);
if(dp[1][1]!=dp[1][0]) cnt[1][1].print();
else cnt[1][1]+=cnt[1][0],cnt[1][1].print();
return 0;
}