BZOJ 4455: [Zjoi2016]小星星(容斥+树形dp)
解题思路
首先题目中有两个限制,第一个是两个集合直接必须一一映射,第二个是重新标号后,\(B\)中两点有边\(A\)中也必须有。发现限制\(2\)比较容易满足,考虑化简限制\(1\)。令\(f(S)\)表示重标号后至多出现在\(S\)中的标号且满足条件\(2\)的方案数,令\(g(S)\)表示重标号后恰好出现在\(S\)中的标号满足条件\(2\)的方案数。这应该是容斥里的一个套路。那么有转移方程:
\]
然后问题就转化成为求\(f(S)\)了。令\(h[i][j]\)表示\(i\)点重新标号后是\(j\)的方案数。那么转移的时候考虑\(x\)的儿子\(u\)产生的贡献,可以枚举\(u\)的重标号,然后看他们两个的重标号之间有没有边,如果有的话\(cnt+=h[u][j]\),最后\(u\)对\(h[i][j]\)的贡献就为\(cnt\)。时间复杂度\(O(2^n*n^3)\),在下人丑常数大,\(bzoj\)卡了半天才过。。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int MAXN = 18;
typedef long long LL;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
}
int n,m,head[MAXN],cnt,a[MAXN][MAXN],zz[MAXN];
int to[MAXN<<1],nxt[MAXN<<1],tot;
LL g[MAXN][MAXN],ans,now;
bool use[MAXN];
void out(LL x){
if(!x) return ;
out(x/10);putchar('0'+x%10);
}
inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}
void dfs(int x,int f){
int u;LL sum;
for(register int i=1;i<=tot;i++) g[x][i]=1;
for(register int i=head[x];i;i=nxt[i]){
u=to[i];if(u==f) continue;dfs(u,x);
for(register int j=1;j<=tot;j++){sum=0;
for(register int k=1;k<=tot;k++)
if(a[zz[j]][zz[k]]) sum+=g[u][k];
g[x][j]*=sum;
}
}
}
int main(){
n=rd(),m=rd();int x,y;
for(register int i=1;i<=m;i++){
x=rd(),y=rd();
a[x][y]=a[y][x]=1;
}
for(register int i=1;i<n;i++){
x=rd(),y=rd();
add(x,y),add(y,x);
}int num;
for(register int S=1;S<1<<n;S++){
tot=0;num=0;now=0;
for(register int i=1,T=S;T;T>>=1,i++)
if(T&1) num++,zz[++tot]=i;
num=n-num;dfs(1,0);for(register int i=1;i<=tot;i++) now+=g[1][i];
if(num&1) ans-=now;else ans+=now;
}
if(!ans) putchar('0');else out(ans);
return 0;
}
BZOJ 4455: [Zjoi2016]小星星(容斥+树形dp)的更多相关文章
- 【BZOJ 4455】 4455: [Zjoi2016]小星星 (容斥原理+树形DP)
4455: [Zjoi2016]小星星 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 426 Solved: 255 Description 小Y是 ...
- 4455[Zjoi2016]小星星 容斥+dp
4455: [Zjoi2016]小星星 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 527 Solved: 317[Submit][Status] ...
- 【BZOJ-4455】小星星 容斥 + 树形DP
4455: [Zjoi2016]小星星 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 204 Solved: 137[Submit][Status] ...
- bzoj 4455 [Zjoi2016]小星星 树形dp&容斥
4455: [Zjoi2016]小星星 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 643 Solved: 391[Submit][Status] ...
- BZOJ 4455: [Zjoi2016]小星星 [容斥原理 树形DP]
4455: [Zjoi2016]小星星 题意:一个图删掉一些边形成一棵树,告诉你图和树的样子,求让图上的点和树上的点对应起来有多少方案 看了很多题解又想了一段时间,感觉题解都没有很深入,现在大致有了自 ...
- UOJ185 ZJOI2016 小星星 容斥、树形DP
传送门 先考虑一个暴力的DP:设\(f_{i,j,S}\)表示点\(i\)映射到了图中的点\(j\),且点\(i\)所在子树的所有点映射到了图中的集合\(S\)时的映射方案数,转移暴力地枚举子集即可, ...
- 【BZOJ 4455】 [Zjoi2016]小星星 容斥计数
dalao教导我们,看到计数想容斥……卡常策略:枚举顺序.除去无效状态.(树结构) #include <cstdio> #include <cstring> #include ...
- BZOJ 4455: [Zjoi2016]小星星
Sol 容斥原理+树形DP. 这道题用的容斥思想非常妙啊!主要的思路就是让所有点与S集合中的点对应,可以重复对应,并且可以不用对应完全(意思是是S的子集也可以).这样他有未对应完全的,那就减去,从全都 ...
- BZOJ4455 ZJOI2016小星星(容斥原理+树形dp)
相当于给树上的每个点分配一个编号使父亲和儿子间都有连边. 于是可以考虑树形dp:设f[i][j][k]为i号点的编号为j,其子树中编号集合为k的方案数.转移显然.然而复杂度3n·n3左右,具体我也不知 ...
随机推荐
- mongoose 常用数据库操作 删除
删除 Model.remove(conditions, [callback]) try.js var User = require("./user.js"); function d ...
- stylus 使用小技巧(1)
mixins.styl $pink_color = #fc566a $yellow_color = #fee246 add(a) a = unit(a, rem) pic_position($widt ...
- 帝国cms返回首页
<a href="[!--news.url--]">返回首页</a>
- 导出EXCEL(带数据)
/* * 导出EXCEL * @param req * @param resp * @param model * @param info * @return */ @RequestMapping(va ...
- 区间dp+预处理——cf1278F(难题)
感觉很难的区间dp,主要是状态难想 /* 对于一个区间[i,j],设其最小的颜色编号是c=Min[i,j],那么该区间显然有一大段是以c为底的 设这个颜色在该区间出现位置的两端是L[c],R[c],那 ...
- 【系统安全性】二、Web攻击与防范
二.Web攻击与防范 1.XSS攻击 跨站脚本攻击(Cross Site Scripting),因为简写CSS,与层叠样式表(Cascading Style Sheets)有歧义,所以取名XSS 原理 ...
- CF D. Walking Between Houses (贪心)
题意: 现在有n个房子排成一列,编号为1~n,起初你在第1个房子里,现在你要进行k次移动,每次移动一都可以从一个房子i移动到另外一个其他的房子j里(i != j),移动的距离为|j - i|.问你进过 ...
- python url编码与解码
上代码 #codeing:utf-8 from urllib import parse ori_url_10='http://192.168.0.10:3080/asg/portal.do?call= ...
- Linux权限简析
- C++——函数及调用
1.函数调用:实参初始化形参:控制权交给被调函数 2.函数返回(return语句):返回return中的值:控制权交回主函数 3.参数传递 传值 传引用 传指针 初始值 不变,拷贝给形参 可变,形 ...