uoj#185 小星星

dp[i][j]表示以i为根,且i在原图上对应的点为点j的方案数

可能多个点会对应到原图中的一个点,所以要容斥处理一下

枚举都对应到了哪些点

dp转移方程为 dp[u][j]=π(v∈son[i])∑(k∈adj[j])dp[v][k]

子树间方案数是乘起来啊qaq

然后就是容斥了

bin数组是2^i

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
typedef long long ll;

const int maxn = 30;

int n,m,cnt;
ll f[maxn][maxn],ans,res;
int a[maxn],bin[maxn];

int h[maxn],size,h1[maxn],size1;
struct E{
    int to,next;
}e[maxn<<5],e1[maxn<<5];
void add(int u,int v){
    e[++size].to=v;
    e[size].next=h[u];
    h[u]=size;
}
void add1(int u,int v){
    e1[++size1].to=v;
    e1[size1].next=h1[u];
    h1[u]=size1;
}

void dfs(int u,int par){
    for(int i=h1[u];i!=-1;i=e1[i].next){
        int v=e1[i].to;
        if(v==par) continue;
        dfs(v,u);
    }
    
    for(int i=1;i<=cnt;i++){
        f[u][a[i]]=1;
    
        for(int j=h1[u];j!=-1;j=e1[j].next){
            int v=e1[j].to;
            ll res=0;
            if(v==par) continue;
            for(int k=h[a[i]];k!=-1;k=e[k].next){
                res+=f[v][e[k].to];
            }
            f[u][a[i]]*=res;
            if(!res) break;
        }
    }
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}

int main(){
    memset(h,-1,sizeof(h));
    memset(h1,-1,sizeof(h1));
    n=read(),m=read();
    bin[0]=1; for(int i=1;i<=n;i++) bin[i]=bin[i-1]<<1;
    int u,v;
    for(int i=1;i<=m;i++){
        u=read(),v=read();
        add(u,v),add(v,u);
    }
    for(int i=1;i<n;i++){
        u=read(),v=read();
        add1(u,v),add1(v,u);
    }
    
    for(int i=1;i<(1<<n);i++){
        cnt=0;
        memset(f,0,sizeof(f));
        for(int j=0;j<n;j++){
            if(i&(1<<j)) a[++cnt]=j+1;
        }
        dfs(1,0);
        res=0;
        for(int j=1;j<=cnt;j++) res+=f[1][a[j]];
        if((n-cnt)&1) ans-=res; else ans+=res;
    }
    printf("%lld\n",ans);
    
    return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/10412062.html