ref

总的来说,就是

  1. 容斥转化为点对应到点集问题。
  2. 树形 dp 解决转化后的问题。
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, hea[19], cnt, uu, vv;
bool w[19][19];
ll dp[19][19], ans;
struct Edge{
int too, nxt;
}edge[105];
vector<int> vec;
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
void dfs(int x, int f){
for(int i=0; i<vec.size(); i++)
dp[x][vec[i]] = 1;
for(int j=hea[x]; j; j=edge[j].nxt){
int t=edge[j].too;
if(t!=f){
dfs(t, x);
for(int i=0; i<vec.size(); i++){
ll s=0;
for(int k=0; k<vec.size(); k++){
if(w[vec[i]][vec[k]]){
s += dp[t][vec[k]];
}
}
dp[x][vec[i]] *= s;
}
}
}
}
int main(){
cin>>n>>m;
for(int i=1; i<=m; i++){
scanf("%d %d", &uu, &vv);
w[uu][vv] = w[vv][uu] = true;
}
for(int i=1; i<n; i++){
scanf("%d %d", &uu, &vv);
add_edge(uu, vv);
add_edge(vv, uu);
}
for(int i=0; i<(1<<n); i++){
vec.clear();
for(int j=0; j<n; j++)
if(i&(1<<j))
vec.push_back(j+1);
memset(dp, 0, sizeof(dp));
dfs(1, 0);
ll tmp=0;
for(int j=0; j<vec.size(); j++)
tmp += dp[1][vec[j]];
if((n&1)==(vec.size()&1)) ans += tmp;
else ans -= tmp;
}
cout<<ans<<endl;
return 0;
}

最新文章

  1. animation_Frame动画图片轮播
  2. HTML是什么?如何使用?
  3. Smart_Script
  4. orleans/Documentation
  5. [Linux]服务管理:rpm包, 源码包
  6. 在Eclipse在使用JUnit4单元测试(0基础知识)
  7. java中的volatile关键字
  8. p1349星屑幻想
  9. Java 强引用 软引用 弱引用 虚引用详解
  10. ide phpStorm更换主题
  11. scrapy之基础概念与用法
  12. 记无法用被动方式登录远程linux主机的原因
  13. TensorFlow 分布式实践
  14. delphi Ribbon 111
  15. read()函数的困惑
  16. 关于Java泛型深入理解小总结
  17. RestFramework
  18. 偶遇 sqlserver 参数嗅探
  19. POJ 3895 Cycles of Lanes (dfs)
  20. CodeForces - 894A-QAQ(思维)

热门文章

  1. html标签补充
  2. springMvc 添加定时任务
  3. 2016多校训练3_1007(hdu5758 Explorer Bo)
  4. 使用纯css实现波浪效果
  5. 【MFC】将当前的日期转化为1970年开始的秒计数
  6. 【C++】【MFC】创建新的线程函数
  7. Android商城开发系列(十三)—— 首页热卖商品布局实现
  8. Windows下用cmd命令安装及卸载服务[转]
  9. HDU汉诺塔系列
  10. 如何查看CRM WebUI,C4C和Hybris里的页面技术信息