博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[ZJOI2016]小星星
阅读量:4955 次
发布时间:2019-06-12

本文共 4248 字,大约阅读时间需要 14 分钟。

题目描述

小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品。她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星。

有一天她发现,她的饰品被破坏了,很多细线都被拆掉了。这个饰品只剩下了n?1条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树。小Y找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星。如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上也有细线相连。小Y想知道有多少种可能的对应方式。

只有你告诉了她正确的答案,她才会把小饰品做为礼物送给你呢。

输入输出格式

输入格式:

第一行包含个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

输出格式:

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

输入输出样例

输入样例#1:

4 3

1 2
1 3
1 4
4 1
4 2
4 3

输出样例#1:

6


题解

首先看到n<=17,第一反应就是撞鸭

然后想了一会儿觉得是可行的,就是设\(f[i][j][S]\)表示在树上的点i对应图上的点j,且i的子树选取图上的点的情况是\(S\)
然后dp就直接无脑枚举这个点u对应图上的什么,然后再枚举点u的状态,然后再枚举v对应图上的什么,然后再枚举点v的状态,然后ta就\(MLE+TLE\)成70分了其实不开longlong卡一下空间可以到90

#include
#include
#include
#include
#include
# define LL long longconst int M = 18 ;const int N = (1 << 17) + 1 ;using namespace std ;int n , m , size[M] ;vector < int > G[M] , vec[M] , sit[M] ;LL f[M][M][N] ;LL Ans ;inline int Gsz(int x) { int ret = 0 ; for(int i = 1 ; i <= n ; i ++) if(x & (1 << (i - 1))) ++ ret ; return ret ;}void dfs(int u , int father) { size[u] = 1 ; for(int i = 1 ; i <= n ; i ++) f[u][i][(1 << (i - 1))] = 1 ; for(int e = 0 , v ; e < vec[u].size() ; e ++) { v = vec[u][e] ; if(v == father) continue ; dfs(v , u) ; for(int i = 0 , S ; i < sit[size[u]].size() ; i ++) { S = sit[size[u]][i] ; for(int id = 1 ; id <= n ; id ++) { if(!(S & (1 << (id - 1)))) continue ; for(int j = 0 , T ; j < sit[size[v]].size() ; j ++) { T = sit[size[v]][j] ; if(S & T) continue ; for(int k = 0 , vid ; k < G[id].size() ; k ++) { vid = G[id][k] ; if(!(T & (1 << (vid - 1)))) continue ; f[u][id][S | T] += f[u][id][S] * f[v][vid][T] ; } } } } size[u] += size[v] ; }}int main() { scanf("%d%d",&n,&m) ; for(int i = 1 , u , v ; i <= m ; i ++) { scanf("%d%d",&u,&v) ; G[u].push_back(v) ; G[v].push_back(u) ; } for(int i = 1 , u , v ; i < n ; i ++) { scanf("%d%d",&u,&v) ; vec[u].push_back(v) ; vec[v].push_back(u) ; } for(int i = 0 ; i < (1 << n) ; i ++) sit[Gsz(i)].push_back(i) ; dfs(1 , 1) ; for(int i = 1 ; i <= n ; i ++) Ans += f[1][i][(1 << n) - 1] ; printf("%lld\n",Ans) ; return 0 ;}

然后这么做复杂度显然不对,我们考虑一个正确的方法

我们考虑这道题用撞鸭的目的是什么?
判重!
就是为了每个点映射图上的点不要重复
所以我们可以考虑容斥
先让每个点随便对应图上的点,只要能对应上就行(两点之间有边),然后减去有一个点被选重复的方案数,再加上有两个点被选重复的方案数-...+..,以此类推
复杂度就是\(2^n*n^3\)

#include
#include
# define LL long longconst int M = 18 ;using namespace std ;int n , m , Sit ;vector < int > G[M] , vec[M] ;LL f[M][M] , Ans ;void dfs(int u , int father) { for(int i = 1 ; i <= n ; i ++) f[u][i] = 1 ; for(int i = 0 , v ; i < vec[u].size() ; i ++) { v = vec[u][i] ; if(v == father) continue ; dfs(v , u) ; for(int id = 1 ; id <= n ; id ++) { if(Sit & (1 << (id - 1))) continue ; LL temp = 0 ; for(int j = 0 , idv ; j < G[id].size() ; j ++) { idv = G[id][j] ; if(Sit & (1 << (idv - 1))) continue ; temp += f[v][idv] ; } f[u][id] *= temp ; } }}inline void query(int ret) { dfs(1 , 1) ; for(int i = 1 ; i <= n ; i ++) { Ans += ret * f[1][i] ; for(int j = 1 ; j <= n ; j ++) f[j][i] = 0 ; }}int main() { scanf("%d%d",&n,&m) ; for(int i = 1 , u , v ; i <= m ; i ++) { scanf("%d%d",&u,&v) ; G[u].push_back(v) ; G[v].push_back(u) ; } for(int i = 1 , u , v ; i < n ; i ++) { scanf("%d%d",&u,&v) ; vec[u].push_back(v) ; vec[v].push_back(u) ; } for(int i = 0 , cnt = 0 ; i < (1 << n) ; i ++) { cnt = 0 ; Sit = i ; for(int j = 1 ; j <= n ; j ++) if(i & (1 << (j - 1))) ++ cnt ; cnt % 2 ? query(-1) : query(1) ; } printf("%lld\n",Ans) ; return 0 ;}

转载于:https://www.cnblogs.com/beretty/p/10288311.html

你可能感兴趣的文章
[Scrum]11.11
查看>>
autoMapper dotnetcore webapi 自动添加映射 abp
查看>>
chrome开发者工具那点事
查看>>
geant4 资料汇总
查看>>
快学UiAutomator创建第一个实例
查看>>
Python中的类方法、实例方法、静态方法
查看>>
每日一记======>Django笔记 2012.08.22
查看>>
以前积攒的一个用Java程序生成验证码的代码
查看>>
[python]CompressionError: bz2 module is not available
查看>>
有趣的电影墙站点
查看>>
Java正则表达式的语法与示例
查看>>
#RANK_3 1191:棋盘分割
查看>>
whereis查看软件的安装路径
查看>>
(3)Gojs model简介
查看>>
python 推导式
查看>>
GIS开发之计算四参数,七参数
查看>>
2016-2017-2 《Java程序设计》第3周学习总结
查看>>
富文本编辑器里提取简介--正则表达式替换标签
查看>>
CCF系列之字符串匹配(201409-3)
查看>>
xss payloads ----full
查看>>