zoukankan      html  css  js  c++  java
  • 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
    ",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;
    }
    
    
  • 相关阅读:
    【递推】【概率】Gym
    【坐标变换】【二维偏序】【线段树】Gym
    【DLX算法】hdu3498 whosyourdaddy
    【DLX算法】poj2676 Sudoku
    【Pollard-rho算法】【DFS】poj2429 GCD & LCM Inverse
    Pollard-rho算法:模板
    【筛法求素数】【推导】【组合数】UVALive
    【二项式定理】【DFS】UVALive
    【并查集】【枚举倍数】UVALive
    【Floyd算法】Gym
  • 原文地址:https://www.cnblogs.com/sssy/p/8471443.html
Copyright © 2011-2022 走看看