【bzoj3349】[Zjoi2016]小星星

xiaoxiao2021-02-28  100

容斥+树形dp

SSf[x][y]xyx

#include <bits/stdc++.h> #define gc getchar() #define ll long long #define N 18 #define M N*N/2 using namespace std; int n,m,x,y,first[N],First[N],Number,number,q[N],w; int mp[N][N],fa[N]; ll dp[N][N],Ans; struct edge { int from,to,next; void add(int x,int y) { from=x,to=y,next=first[x],first[x]=number; } }e[M]; int read() { int x=1; char ch; while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1; int s=ch-'0'; while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0'; return s*x; } void tree_dp(int x) { for (int i=1;i<=w;i++) dp[x][q[i]]=1; for (int i=first[x];i;i=e[i].next) if (fa[x]!=e[i].to) { fa[e[i].to]=x; tree_dp(e[i].to); for (int j=1;j<=w;j++) { ll sum=0; for (int k=1;k<=w;k++) if (mp[q[j]][q[k]]) sum+=dp[e[i].to][q[k]]; dp[x][q[j]]*=sum; } } } int main() { n=read(),m=read(); for (int i=1;i<=m;i++) { x=read(),y=read(); mp[x][y]=mp[y][x]=1; } for (int i=1;i<n;i++) { x=read(),y=read(); e[++number].add(x,y); e[++number].add(y,x); } Ans=0; for (int i=1;i<(1<<n);i++) { memset(dp,0,sizeof(dp)); w=0; for (int k=i,j=1;k;k>>=1,j++) if (k&1) q[++w]=j; tree_dp(1); ll sum=0; for (int j=1;j<=w;j++) sum+=dp[1][q[j]]; if ((n&1)==(w&1)) Ans+=sum; else Ans-=sum; } printf("%lld\n",Ans); return 0; }
转载请注明原文地址: https://www.6miu.com/read-70309.html

最新回复(0)