先考虑一个错误的DP,
fi,j
表示子树
i
中,
我们考虑多一维状态
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
int n,m,st[20],top;
ll f[20][20],ans;
bool mp[20][20];
struct edge
{
int t;
edge *next;
}*con[20];
void ins(int x,int y)
{
edge *p=new edge;
p->t=y;
p->next=con[x];
con[x]=p;
}
void dp(int v,int fa,int s)
{
for(int i=1;i<=top;i++) f[v][st[i]]=1;
for(edge *p=con[v];p;p=p->next)
if(p->t!=fa)
{
dp(p->t,v,s);
for(int i=1;i<=top;i++)
{
ll cal=0;
for(int j=1;j<=top;j++)
cal+=f[p->t][st[j]]*mp[st[i]][st[j]];
f[v][st[i]]*=cal;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x][y]=mp[y][x]=1;
}
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
for(int s=0;s<(1<<n);s++)
{
top=0;
for(int i=0;i<n;i++)
if((s>>i)&1) st[++top]=i+1;
dp(1,0,s);
for(int i=1;i<=top;i++)
ans+=f[1][st[i]]*((n-top)&1?-1:1);
}
printf("%lld",ans);
return 0;
}