bzoj4455: [Zjoi2016]小星星

传送门

题解传送门

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=18;
typedef long long LL;
using namespace std;
int n,m,a[N][N],b[N];

template<typename T>void read(T &x)  {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

int ecnt,fir[N],nxt[N<<2],to[N<<2];
void add(int u,int v) {
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
    nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
}

LL dp[N][N],ans;
void dfs(int x,int fa) {
    for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) 
        dfs(to[i],x);
    For(i,1,b[0]) {
        dp[x][i]=1;
        for(int j=fir[x];j;j=nxt[j]) if(to[j]!=fa) {
            LL tp=0;
            For(k,1,b[0]) if(a[b[i]][b[k]])
                tp+=dp[to[j]][k];
            dp[x][i]*=tp; if(!dp[x][i]) break;
        }
    }
}

int main() {
#ifdef DEBUG
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
    read(n); read(m);
    For(i,1,m) {
        int x,y;
        read(x); read(y);
        a[x][y]=a[y][x]=1;
    }
    For(i,2,n) {
        int x,y;
        read(x); read(y);
        add(x,y);
    }
    int nn=(1<<n);
    For(i,1,nn-1){
        int sum=n; LL w=0; b[0]=0;
        For(j,1,n) if(i&(1<<(j-1))) { sum--; b[++b[0]]=j; }
        dfs(1,0);
        For(i,1,b[0]) w+=dp[1][i];
        if(sum&1) ans-=w; 
        else ans+=w;
    }
    printf("%lld\n",ans);
    return 0;
}
/*
4 3
1 2
1 3
1 4
4 1
4 2
4 3
*/
View Code

 

posted @ 2018-03-12 19:28  啊宸  阅读(165)  评论(0编辑  收藏  举报