【BZOJ 4455】 4455: [Zjoi2016]小星星 (容斥原理+树形DP)
2024-08-26 07:52:27
4455: [Zjoi2016]小星星
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 426 Solved: 255Description
小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)/2Output
输出共1行,包含一个整数表示可能的对应方式的数量。如果不存在可行的对应方式则输出0。Sample Input
4 3
1 2
1 3
1 4
4 1
4 2
4 3Sample Output
6HINT
Source
【分析】
很久之前的比赛的一题。【好题啊但是我为什么没有写题解?
先不考虑每个点一一对应的话,对应关系正确当且仅当树上有的边,对应到原来的无向图上的边也有。
f[x][i]表示x这个点对应i这个点的情况下,x这棵子树的对应关系正确的方案数。
这个树形DP即可,n^3。
但是要保证一一对应,那么可能有一些点没有被对应,所以用容斥。
枚举没有对应的点,若为奇则减,为偶则加。
【记得好像不用边目录会T?
【好像这种“恰好”或者“一一对应”的题目都很经常用容斥,你不能保证要保证的东西,容斥一下就会变得简单
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0xfffffff
#define Maxn 20
#define LL long long bool c[Maxn][Maxn];
int fa[Maxn],first[Maxn]; int n,m; struct node
{
int x,y,next;
}t[*Maxn];int len; void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
} void dfs(int x,int f)
{
fa[x]=f;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
{
dfs(t[i].y,x);
}
} LL f[Maxn][Maxn]; void get_f(int x,int s)
{
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
{
get_f(t[i].y,s);
}
for(int i=;i<=n;i++) if(((<<i-)&s)==)
{
f[x][i]=;
for(int j=first[x];j;j=t[j].next) if(t[j].y!=fa[x])
{
LL now=;
int y=t[j].y;
for(int k=;k<=n;k++) if(c[i][k])
{
now+=f[y][k];
}
f[x][i]*=now;
}
}
else f[x][i]=;
} int main()
{
memset(c,,sizeof(c));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
c[x][y]=c[y][x]=;
}
memset(first,,sizeof(first));
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
dfs(,);
int mx=(<<n)-;
LL ans=;
for(int i=;i<=mx;i++)
{
// memset(f,0,sizeof(f));
get_f(,i);
int h=,now=i;
LL sum=;
while(now)
{
if(now&) h++;
now/=;
}
for(int j=;j<=n;j++) sum+=f[][j];
if(h%==) ans+=sum;
else ans-=sum;
}
// memset(f,0,sizeof(f));
get_f(,);
for(int j=;j<=n;j++) ans+=f[][j];
printf("%lld\n",ans);
return ;
}
2017-04-20 17:23:11
最新文章
- 汽车ABS系统-第一周作业
- JSON.stringify()
- SQL SERVER代码生成器必备
- jQuery中find和filter的区别
- DetailsView的添加,修改,删除,查询
- DELL R710服务器做RAID5磁盘阵列图文教程
- centos安装配置nginx
- 【转】Android开发实践:自定义带消息循环(Looper)的工作线程
- 小白日记6:kali渗透测试之被动信息收集(五)-Recon-ng
- php 的一个pg_fetch_assoc的怪问题
- servlet清晰理解
- C# datetimePicker控件格式设置
- 逆向 Framework.jar
- PL SQL Developer报错框乱码
- 一个RESTful+MySQL程序
- Git 常用命令速查表(图文+表格)
- Tomcat内核之类加载器工厂
- EOJ2018.10 月赛(A 数学+思维题)
- LOJ 3089: 洛谷 P5319: 「BJOI2019」奥术神杖
- pop控制器
热门文章
- C.Fountains(Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2)+线段树+RMQ)
- es6新语法Object.assign()
- NASA: A Closer View of the Moon(近距离观察月球)
- (2)剑指Offer之二维数组查找和替换空格问题
- nvidia tx1使用记录--基本环境搭建
- RAID总结
- react native系列 - 从零开始构建
- selenium webdriver操作各浏览器
- PHP–图像XX因其本身有错无法显示
- C++ 静多态与动多态