树的点到图的点是双射
枚举哪些点可以映射到
然后dp容斥
复杂度 $2^n*n^3$
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a),i##_end=(b);i<=i##_end;++i) #define For(i,a,b) for(int i=(a),i##_end=(b);i<i##_end;++i) #define per(i,a,b) for(int i=(b),i##_st=(a);i>=i##_st;--i) #define fi first #define se second #define pb push_back #define mp make_pair #define dbg(x) cerr<<#x" = "<<x<<endl #define debug(...) fprintf(stderr, __VA_ARGS__) #define Es(x,i) for(Edge *i=G[x];i;i=i->nxt) typedef long long ll; typedef pair<int,int> pii; const int inf=~0u>>1,mod=1e9+7; inline int rd() { int x,c,f=1;while(!isdigit(c=getchar()))f=c!=‘-‘;x=c-‘0‘; while(isdigit(c=getchar()))x=x*10+c-‘0‘;return f?x:-x; } const int N=18; struct Edge{int v;Edge*nxt;}pl[N*N],*cur=pl,*G[N]; inline void ins(int u,int v){*cur=(Edge){v,G[u]},G[u]=cur++;} char g[N][N]; int n,m,a[N],tot; ll f[N][N]; inline void Dp(int x,int fa=-1){ Es(x,i)if(i->v!=fa){ Dp(i->v,x); } For(i,0,tot){ f[x][i]=1; Es(x,p)if(p->v!=fa){ ll t=0; For(j,0,tot)if(g[a[i]][a[j]]){ t+=f[p->v][j]; } f[x][i]*=t; } } } int main(){ #ifdef flukehn freopen("ex_star2.in","r",stdin); #endif n=rd(),m=rd(); rep(i,1,m){ int u=rd()-1,v=rd()-1; g[u][v]=g[v][u]=1; } ll ans=0; For(i,1,n){ int u=rd()-1,v=rd()-1; ins(u,v),ins(v,u); } For(i,1,1<<n){ tot=0; For(j,0,n)if(i>>j&1)a[tot++]=j; Dp(0); ll p=0; For(j,0,tot)p+=f[0][j]; ans+=((tot&1)?-1:1)*p; } if(ans<0)ans=-ans; cout<<ans<<endl; }