这两道题思路比较像,所以把他们放到一块。

[ZJOI2016]小星星

题目描述

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

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

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

题解

做容斥题有一个基本模型,就是有一个限制,我们直接在转移或者统计复杂度过高,但如果把它放宽一点的话复杂度会降低许多。

然后总的条件数也支持2^n枚举,就可以去考虑容斥。

这个题是说,有一个n个点的无向图和n个点的一棵树,问有多少种一一对应的映射使得在树中有的边,图中也有。

看到树可以联想树形dp,因为我们要求一一对应,所以我们可以考虑设dp[i][j][s]表示以i为根的子树,i对应了图中的j,i子树对应了图中的集合s的方案数。

转移还是比较简单的。

我们观察到这个算法复杂度瓶颈在于枚举s,所以我们考虑能不能去掉。

去掉之后会出现树中的多个点对应了图中的一个点,方案数会算多。

怎么办?这个形式其实已经很明显了,直接套用容斥公式算就好了。

2^n枚举图中选那些点,然后做二维的树形dp就好了。

代码

#include<iostream>
#include<cstdio>
#define N 18
#define R register
using namespace std;
typedef long long ll;
int n,m,tot,head[N],cou[<<N];
ll dp[N][N],ans;
bool a[N][N],jin[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{int n,to;}e[N*N*];
inline void add(int u,int v){
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;
}
void dfs(int u,int fa){
for(R int i=;i<=n;++i)if(!jin[i])dp[u][i]=;else dp[u][i]=;
for(R int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;dfs(v,u);
for(R int j=;j<=n;++j)if(!jin[j]){
ll num=;
for(R int k=;k<=n;++k)if(a[j][k]&&!jin[k])num+=dp[v][k];
dp[u][j]*=num;
}
}
}
int main(){
n=rd();m=rd();int x,y;
for(R int i=;i<=m;++i){
x=rd();y=rd();
a[x][y]=a[y][x]=;
}
for(R int i=;i<n;++i){x=rd();y=rd();add(x,y);add(y,x);}
for(R int i=;i<(<<n);++i){
cou[i]=cou[i>>]+(i&);
for(R int j=;j<=n;++j)jin[j]=(i&(<<j-))!=;
dfs(,);
ll num=;
for(R int j=;j<=n;++j)num+=dp[][j];
if(cou[i]&)ans-=num;else ans+=num;
}
cout<<ans;
return ;
}

[SHOI2016]黑暗前的幻想乡

题目描述

四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖怪涌入了幻想乡,扰乱了幻想乡昔日的秩序。但是幻想乡的建制派妖怪(人类)博丽灵梦和八云紫等人整日高谈所有妖怪平等,幻想乡多元化等等,对于幻想乡目前面临的种种大问题却给不出合理的解决方案。

风见幽香是幻想乡里少有的意识到了问题严重性的大妖怪。她这次勇敢地站了出来参加幻想乡大选,提出包括在幻想乡边境建墙(并让人类出钱),大力开展基础设施建设挽回失业率等一系列方案,成为了大选年出人意料的黑马并顺利地当上了幻想乡的大统领。

幽香上台以后,第一项措施就是要修建幻想乡的公路。幻想乡一共有 nn 个城市,之前原来没有任何路。幽香向选民承诺要减税,所以她打算只修 n-1n−1条公路将这些城市连接起来。但是幻想乡有正好 n-1n−1 个建筑公司,每个建筑公司都想在修路地过程中获得一些好处。虽然这些建筑公司在选举前没有给幽香钱,幽香还是打算和他们搞好关系,因为她还指望他们帮她建墙。所以她打算让每个建筑公司都负责一条路来修。

每个建筑公司都告诉了幽香自己有能力负责修建的路是哪些城市之间的。所以幽香打算 n - 1n−1条能够连接幻想乡所有城市的边,然后每条边都交给一个能够负责该边的建筑公司修建,并且每个建筑公司都恰好修建一条边。

幽香现在想要知道一共有多少种可能的方案呢?两个方案不同当且仅当它们要么修的边的集合不同,要么边的分配方式不同。

题解

这题和上一题相似,有两个限制。

上一题是要满足树中和图中都要有某条边。

这题是要满足我们的生成树中,既要有n个不同的点,还要满足每种颜色的边个出现一次。

如果我们去掉第二个限制,那就变成了生成树计数问题,套用矩阵树定理即可。

然后我们发现面前的这个问题还是可以套用容斥公式直接计算的,于是这道题被愉快的解决了。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define N 18
using namespace std;
typedef long long ll;
const int mod=1e9+;
ll a[N][N];
int n,m,cou[<<N];
bool tag[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline ll power(ll x,ll y){
ll ans=;
while(y){if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;}
return ans;
}
struct node{int x,y;};
vector<node>vec[N];
inline ll ni(ll x){return power(x,mod-);}
inline ll gauss(ll tot){
ll ans=;
for(int i=;i<=tot;++i)
for(int j=i+;j<=tot;++j){
ll t=a[j][i]*ni(a[i][i])%mod;
for(int k=i;k<=tot;++k)a[j][k]=((a[j][k]-t*a[i][k])%mod+mod)%mod;
}
for(int i=;i<=tot;++i)ans=(ans*a[i][i]%mod+mod)%mod;
return ans;
}
inline ll work(){
memset(a,,sizeof(a));
for(int i=;i<n;++i)if(tag[i]){
for(int j=;j<vec[i].size();++j){
int x=vec[i][j].x,y=vec[i][j].y;
a[x][x]++;a[y][y]++;a[x][y]--;a[y][x]--;
}
}
return gauss(n-);
}
int main(){
n=rd();int x,y;
for(int i=;i<n;++i){
m=rd();
for(int j=;j<=m;++j){
x=rd();y=rd();vec[i].push_back(node{x,y});
}
}
ll ans=;
for(int i=;i<(<<n-);++i){
cou[i]=cou[i>>]+(i&);
for(int j=;j<=n-;++j)tag[j]=(i&(<<j-))==;
if(cou[i]&)ans-=work();else ans+=work();
ans=(ans%mod+mod)%mod;
}
cout<<ans;
return ;
}

[ZJOI2016]小星星&[SHOI2016]黑暗前的幻想乡(容斥)的更多相关文章

  1. 【BZOJ4596】[Shoi2016]黑暗前的幻想乡 容斥+矩阵树定理

    [BZOJ4596][Shoi2016]黑暗前的幻想乡 Description 幽香上台以后,第一项措施就是要修建幻想乡的公路.幻想乡有 N 个城市,之间原来没有任何路.幽香向选民承诺要减税,所以她打 ...

  2. BZOJ 4596: [Shoi2016]黑暗前的幻想乡(容斥+Matrix_Tree)

    传送门 解题思路 看到计数想容斥--\(from\) \(shadowice1984\)大爷.首先求出原图的生成树个数比较容易,直接上矩阵树定理,但这样会多算一点东西,会把\(n-2\)个公司的多算进 ...

  3. 洛谷 P4336 黑暗前的幻想乡 —— 容斥+矩阵树定理

    题目:https://www.luogu.org/problemnew/show/P4336 当作考试题了,然而没想出来,呵呵. 其实不是二分图完美匹配方案数,而是矩阵树定理+容斥... 就是先放上所 ...

  4. bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 559  Solved: 325[Submit][Sta ...

  5. bzoj4596[Shoi2016]黑暗前的幻想乡 Matrix定理+容斥原理

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 464  Solved: 264[Submit][Sta ...

  6. P4336 [SHOI2016]黑暗前的幻想乡

    P4336 [SHOI2016]黑暗前的幻想乡 矩阵树定理(高斯消元+乘法逆元)+容斥 ans=总方案数 -(公司1未参加方案数 ∪ 公司2未参加方案数 ∪ 公司3未参加方案数 ∪ ...... ∪ ...

  7. 【BZOJ 4596】 4596: [Shoi2016]黑暗前的幻想乡 (容斥原理+矩阵树定理)

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 324  Solved: 187 Description ...

  8. bzoj4596/luoguP4336 [SHOI2016]黑暗前的幻想乡(矩阵树定理,容斥)

    bzoj4596/luoguP4336 [SHOI2016]黑暗前的幻想乡(矩阵树定理,容斥) bzoj Luogu 题解时间 看一看数据范围,求生成树个数毫无疑问直接上矩阵树定理. 但是要求每条边都 ...

  9. BZOJ4596: [Shoi2016]黑暗前的幻想乡

    Description 四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖 怪涌入了幻想乡,扰乱了幻想乡昔日的秩序.但是幻想乡的建制派妖怪(人类) 博丽灵梦和八云紫等人整日高谈所有妖怪 ...

随机推荐

  1. laravel 关联中的预加载

    预加载 当作为属性访问 Eloquent 关联时,关联数据是「懒加载」的.意味着在你第一次访问该属性时,才会加载关联数据.不过,是当你查询父模型时,Eloquent 可以「预加载」关联数据.预加载避免 ...

  2. IDEA将项目上传至码云/GitHub托管

    怎么将本地的项目放到码云或者GitHub去托管了?(以码云为例) 一.创建远程项目 第一步:点击创建项目 第二步:填写项目相关信息 第三步:复制远程的项目地址,注意:此处码云官方已经给出上传项目方法, ...

  3. [转帖]ipvsadm命令参考及其应用例子

    ipvsadm命令参考及其应用例子 https://blog.csdn.net/orichisonic/article/details/47375227 只是简单创建了 service和添加serve ...

  4. opencv自带fast_math.hpp

    cvRound cvFloor cvCeil cvIsNaN cvIsInf

  5. RandomStringUtils

    System.out.println(RandomStringUtils.random(5));//随机多少个随机字符中文环境乱码 System.out.println(RandomStringUti ...

  6. Decoder is not a @Sharable handler, so can't be added or removed multiple times

    Decoder is not a @Sharable handler, so can't be added or removed multiple times final MyMessageDecod ...

  7. 创建安全客户端Socket

    SocketFactory factory = SSLSocketFactory.getDefault(); Socket socket = factory.create("localhos ...

  8. HeapSter安装(k8s1.12以后废弃了)

    HeapSter InfluxDB(持久存储) Grafana 展示InfluxDB的数据(类似kibana) #安装InfluxDB #github https://github.com/kuber ...

  9. RN 实战 & React Native 实战

    RN 实战 & React Native 实战 https://abc.xgqfrms.xyz/react-native-docs/ 0.59 https://github.com/xgqfr ...

  10. jdbc工具类2..0

    一.创建外部文件 url=jdbc:mysql:///qy66 use=root password=root driver=com.mysql.jdbc.Driver 二.创建工具类 package ...