Description

小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品。她有n颗小星星,用m条彩色的细线串了起来,每条细
线连着两颗小星星。有一天她发现,她的饰品被破坏了,很多细线都被拆掉了。这个饰品只剩下了n?1条细线,但
通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树。小Y找到了这个饰品的设
计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星。如果现在饰品中两颗小星星有细线相连,
那么要求对应的小星星原来的图纸上也有细线相连。小Y想知道有多少种可能的对应方式。只有你告诉了她正确的 答案,她才会把小饰品做为礼物送给你呢。

Input

第一行包含个2正整数n,m,表示原来的饰品中小星星的个数和细线的条数。
接下来m行,每行包含2个正整数u,v,表示原来的饰品中小星星u和v通过细线连了起来。
这里的小星星从1开始标号。保证u≠v,且每对小星星之间最多只有一条细线相连。
接下来n-1行,每行包含个2正整数u,v,表示现在的饰品中小星星u和v通过细线连了起来。 保证这些小星星通过细线可以串在一起。
n<=17,m<=n*(n-1)/2

Output

输出共1行,包含一个整数表示可能的对应方式的数量。 如果不存在可行的对应方式则输出0。

Sample Input

4 3

1 2

1 3

1 4

4 1

4 2

4 3

Sample Output

6

题解

感觉…还是一个很套路的容斥
要你计数合法的映射数列个数,这种玩意一般都是转化成子集dp然后容斥来做
暴力的想法可以设f[i][j][mask]f[i][j][mask]f[i][j][mask]表示树上第iii个点映射到图中是第jjj个,并且已经有maskmaskmask这个状态的点被选取了,转移是n33nn^33^nn33n的
目标把这个3n3^n3n降下来,我们去掉第三维的限制会好做很多
设f[i][j]f[i][j]f[i][j]表示第iii个点映射到图中是第jjj个
显然的,这样会出现不合法的方案被计数
合法的映射大小为nnn,减去至多大小n−1n-1n−1,加上至多大小n−2n-2n−2…
如此容斥,复杂度n32nn^32^nn32n
预处理一下一个点在这个状态下能转移到哪里…卡一下常就过了.

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int stack[20];
inline void write(LL x)
{if(x<0){putchar('-');x=-x;}if(!x){putchar('0');return;}int top=0;while(x)stack[++top]=x%10,x/=10;while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(LL x){write(x);putchar('\n');}
const int MAXN=18;
const int MAXMASK=(1<<17);
int u1[MAXN],u2,bin[25];
int mp[MAXN][MAXN],n,m;
struct edge{int x,y,next;}a[2*MAXN];int len,last[MAXN];
void ins(int x,int y){len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
LL f[MAXN][MAXN],ans;//i->j
bool is[MAXN];
//bitset<20> is;
int nxt[MAXN][MAXMASK][MAXN];
void dp(int x,int fa)
{for(int i=1;i<=n;++i)if(is[i])f[x][i]=1;for(int k=last[x];k;k=a[k].next)if(a[k].y!=fa){int y=a[k].y;dp(y,x);for(int i=1;i<=n;++i)if(is[i]){LL s1=0;for(int j=1;j<=nxt[i][u2][0];++j)s1+=f[y][nxt[i][u2][j]];
//          for(int j=1;j<=n;++j)if(is[j]&&mp[i][j])s1+=f[y][j];f[x][i]*=s1;}}
}
void init()
{for(int u=1;u<=n;++u)for(int i=0;i<bin[n+1];++i)if(i&bin[u]){nxt[u][i][0]=0;for(int j=1;j<=n;++j)if(mp[u][j]&&(i&bin[j]))nxt[u][i][++nxt[u][i][0]]=j;}
}
void dfs(int k,int ct)
{if(k==n+1){dp(1,0);LL temp=0;for(int j=1;j<=n;++j)if(is[j])temp+=f[1][j];if((n-ct)&1)ans-=temp;else ans+=temp;return ;}is[k]=true;u2|=bin[k];dfs(k+1,ct+1);is[k]=false;u2^=bin[k];dfs(k+1,ct);
}
int main()
{//  freopen("5.in","r",stdin);bin[1]=1;for(int i=2;i<=20;++i)bin[i]=bin[i-1]<<1;n=read();m=read();for(int i=1;i<=m;++i){int x=read(),y=read();mp[x][y]=mp[y][x]=1;u1[x]|=bin[y];u1[y]|=bin[x];}for(int i=1;i<n;++i){int x=read(),y=read();ins(x,y);ins(y,x);}init();dfs(1,0);pr2(ans);return 0;
}

[bzoj4455][容斥原理][DP]小星星相关推荐

  1. bzoj4455 loj2091 [Zjoi2016]小星星 容斥原理+树形DP(+状压DP?)

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4455 https://loj.ac/problem/2091 题解 很不错的一道题.(不过在当 ...

  2. 2019.02.09 bzoj4455: [Zjoi2016]小星星(容斥原理+dp)

    传送门 题意简述:给一张图和一棵树(点数都为n≤17n \le17n≤17),问有多少种给树的标号方法方法使得图中去掉多余的边之后和树一模一样. 思路: 容斥好题啊. 考虑fi,jf_{i,j}fi, ...

  3. [BZOJ4455][UOJ185][Zjoi2016]小星星(树形DP+容斥)

    将问题抽象化: 一个nnn个节点的树,和一个n" role="presentation" style="position: relative;"> ...

  4. ARC101E Ribbons on Tree 容斥原理+dp

    题目链接 https://atcoder.jp/contests/arc101/tasks/arc101_c 题解 直接容斥.题目要求每一条边都被覆盖,那么我们就容斥至少有几条边没有被覆盖. 那么没有 ...

  5. 使用MAKER进行注释: 如何避免多轮MAKER时的重复运算

    通常而言,我们会运行不只一轮的MAKER.如果参考组序列没有变化,那么有一些计算只需要做一次就行了,例如将EST, Repeat和Protein序列比对到参考基因组,得到它们对应的位置. 我们有三种方 ...

  6. 【BZOJ4455】【UOJ185】【ZJOI2016】小星星(树形DP,容斥原理)

    Description http://uoj.ac/problem/185 Solution 单考虑下面Code中的那个dp函数,设fi,jfi,jf_{i,j}表示iii映射到j" rol ...

  7. bzoj4455UOJ185 [Zjoi2016]小星星(树形DP+容斥原理)

    bzoj4455&UOJ185 [Zjoi2016]小星星 原题地址: http://www.lydsy.com/JudgeOnline/problem.php?id=4455 http:// ...

  8. 信息学竞赛中的数学知识 --- 容斥原理

    C++基础数论-----容斥原理 C++基础数论-----容斥原理_C2020lax的博客-CSDN博客_容斥原理c++ C++数论容斥原理----无关的元素 C++数论容斥原理----无关的元素 - ...

  9. 冬令营2015 酱油记

    Day0: 首先是报到,然后发现浙大寝室没网...又木有熟悉的学长可以借个账号,所以就去老师的宾馆蹭网络,做了道USACO的题,看了点论文就到晚饭时间了.晚上是开营仪式,各种发言什么的,还见到了传说中 ...

最新文章

  1. C语言经典例73-反向输出一个链表
  2. Android Studio 使用Lambda
  3. 微信小程序研发问题梳理:翻页:下拉:缓存:canvas:富文本:分享
  4. LeetCode每日打卡 - 汉明距离总和
  5. 存储过程批量执行脚本
  6. HDU 1512 Monkey King(左偏树模板题)
  7. 怎么去掉word标题前的黑点
  8. sqlserver CASE WHEN语句示例
  9. Blackrock的思考与启示
  10. 操作系统:磁盘调度实验之扫描和循环扫描调度算法(含源码和文档)
  11. 我从Web前端开发转到网页游戏开发
  12. 阿里巴巴《Java开发手册》官网最全版本及配套 AJCG(Alibaba Java Coding Guidelines)辅助插件下载
  13. Unity Translate方法使用指南
  14. WARNING: disk usage in log directory [/home/.../.ros/log] is over 1GB. 问题解决办法
  15. 【小程序开发之微信登录】
  16. 去除重复字母Python解法
  17. GeekOS操作系统课程设计 project1
  18. ensp-网络地址转换
  19. 每个程序员都应该阅读的最有影响力的书是什么?
  20. 如何关闭对Instagram帖子的评论

热门文章

  1. smtp协议匿名发送邮件 无需密码、授权码
  2. maven项目中导入mysql中的jdbc驱动时,有以下错误出现,说明你需要更换驱动包版本
  3. 何时对固态盘运行低级格式化或擦除以及使用的工具
  4. 自动驾驶汽车涉及哪些技术?
  5. 接口的多实现和多继承
  6. Java实现简单的图片浏览器
  7. lightoj 1098 A New Function 约数之和(一道奇怪的数论) 整除分块优化
  8. MySQL中的隐藏列!_rowid
  9. 基于ISO13400 (DoIP) 实现车辆刷写
  10. 第一个将短信带到中国的人——杨镭