• 题解 CF53E 【Dead Ends】


    题意:

      给一个n(n<=10)个节点的无向图,图里面有m条边,以这m条边构建生成树,求所有生成树中只含有k个度数为1的点的方案数。

    题解:

      看见这个数量级就一定会想到状态压缩dp...

           那让我们设计一下状态:

           dp[i][j] 表示生成树的状态为i时,所含的度数为1的点的状态j的方案数。

      那么就可以进行状态转移了,每次有两种更新方式:

                        1:加入一条边(也就是一个新点)到原来度数为1的点,相当于替换了。

                        2:把边加到一个度数不为1的节点上。

    时间复杂度:

    O(能过)

    废话少说上代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxs=(1<<11)+10;
    vector<int> mapp[20];
    int dp[maxs][maxs],cnt1[maxs];
    int n,m,k;
    void init(){
        for(int i=1;i<=maxs;i++)
            for(int k=0;k<+15;k++)
                if(i&(1<<k))
                   cnt1[i]++;
    }
    int main(){
        init();
        scanf("%d%d%d",&n,&m,&k);
        int x,y;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y); x--;y--;
            mapp[x].push_back(y);mapp[y].push_back(x);
        }
        for(int i=1;i<=(1<<n)-1;i<<=1) dp[i][i]=1;
        for(int i=1;i<=(1<<n)-1;i++)
            for(int j=i;j;--j&=i)
                if(dp[i][j])
                    for(int e=0;e<n;e++)
                        if(i&(1<<e))
                            for(int r=0;r<mapp[e].size();r++){
                                int to=mapp[e][r],now;
                                if(~i&(1<<to)){
                                    if(cnt1[i]==1) now=i|(1<<to);
                                    else now=j&~(1<<e)|(1<<to);
                                    if(!(now>>to+1)) dp[i|(1<<to)][now]+=dp[i][j];
                                }
                            }
        long long ans=0;
        for(int i=0;i<=(1<<n)-1;i++) 
            if(cnt1[i]==k)
               ans+=dp[(1<<n)-1][i];
        printf("%lld",ans);
        return 0;
    }
    自己选择的路,跪着也要走完
  • 相关阅读:
    九九乘法表
    杨辉三角
    显示计算机界面
    完善3.2
    杨辉三角形
    100以内的素数
    九九乘法表
    杨辉三角
    九九乘法表
    杨辉三角形
  • 原文地址:https://www.cnblogs.com/tonyshen/p/11628151.html
Copyright © 2020-2023  润新知