4596: [Shoi2016]黑暗前的幻想乡

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 257  Solved: 152
[Submit][Status][Discuss]

Description

四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖
怪涌入了幻想乡,扰乱了幻想乡昔日的秩序。但是幻想乡的建制派妖怪(人类)
博丽灵梦和八云紫等人整日高谈所有妖怪平等,幻想乡多元化等等,对于幻想乡
目前面临的种种大问题却给不出合适的解决方案。
风间幽香是幻想乡里少有的意识到了问题的严重性的大妖怪。她这次勇敢的
站了出来参加幻想乡大选。提出包括在幻想乡边境建墙(并让人类出钱),大力
开展基础设施建设挽回失业率等一系列方案,成为了大选年出人意料的黑马并顺
利的当上了幻想乡的大统领。
幽香上台以后,第一项措施就是要修建幻想乡的公路。幻想乡有 N 个城市,
之间原来没有任何路。幽香向选民承诺要减税,所以她打算只修 N- 1 条路将
这些城市连接起来。但是幻想乡有正好 N- 1 个建筑公司,每个建筑公司都想
在修路的过程中获得一些好处。
虽然这些建筑公司在选举前没有给幽香钱,幽香还是打算和他们搞好关系,
因为她还指望他们帮她建墙。所以她打算让每个建筑公司都负责一条路来修。
每个建筑公司都告诉了幽香自己有能力负责修建的路是哪些城市之间的。所
以幽香打算选择 N-1 条能够连接幻想乡所有城市的边,然后每条边都交给一
个能够负责该边的建筑公司修建,并且每个建筑公司都恰好修一条边。
幽香现在想要知道一共有多少种可能的方案呢?两个方案不同当且仅当它
们要么修的边的集合不同,要么边的分配方式不同。

Input

第一行包含一个正整数 N(N<=17), 表示城市个数。
接下来 N-1 行,其中第 i行表示第 i个建筑公司可以修建的路的列表:
以一个非负数mi 开头,表示其可以修建 mi 条路,接下来有mi 对数,
每对数表示一条边的两个端点。其中不会出现重复的边,也不会出现自环。

Output

仅一行一个整数,表示所有可能的方案数对 10^9 + 7 取模的结果。
 

Sample Input

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

Sample Output

17
详细地讲一下
不要问为什么,这道题用容斥原理+矩阵树定理
1.矩阵树定理可以求一个单位权图的生成树的个数,这个东西可以自己上网找一下。
2.容斥原理:
首先我们想一下,题目要求每个公司选一条自己能建的边,那么很好啊,我们把每个人的边都加进去,跑矩阵树定理,不就出来了吗?当然不了,因为可能出现某个人的边没被选。这很讨厌,那么我们就要减去这些情况,这些情况都包含什么情况呢?假如一号公司的边没被选中,那么这些情况是要减掉的,不如我们把一号公司的边全删掉,再跑矩阵树定理,加上,然后把二号公司的边都删去,然后。。。是不是就删去了所有那些有人没选的情况?不,这样删多了,因为我们去掉一号公司的边,跑矩阵树定理,也把二号公司没选的方案减了,跑二号公司时,这些情况也减去了,就减多了,那么怎么加上这些情况呢?不如我们把一号公司二号公司的边全删掉,再跑。。。一直这样,这就是容斥原理。。。
2^n枚举一个状态,一个位是一表示这个公司的所有边都加进去了,如果公司%2的数量和总数%2相等,就加上,否则减去。
记住数组要开大,边数有17*16/2种。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 30
#define mod 1000000007
struct edge
{
int u[],v[],size;
}x[N];
int n;
ll ans;
ll a[N][N],d[N][N],g[N][N];
ll gauss()
{
ll f=,ret=;
for(int i=;i<=n;++i)
{
for(int j=i+;j<=n;++j)
{
ll A=g[i][i],B=g[j][i];
while(B)
{
ll t=A/B; A%=B; swap(A,B);
for(int k=i;k<=n;++k)
g[i][k]=((g[i][k]-t*g[j][k]%mod)%mod+mod)%mod;
for(int k=i;k<=n;++k) swap(g[i][k],g[j][k]);
f=-f;
}
}
if(!a[i][i]) return ;
}
for(int i=;i<=n;++i) ret=ret*g[i][i]%mod;
ret=(ret*f%mod+mod)%mod;
return ret;
}
void solve()
{
for(int i=;i<<<n;++i)
{
memset(a,,sizeof(a));
memset(g,,sizeof(g));
memset(d,,sizeof(d));
int tot=;
for(int j=;j<=n;++j) if(i&(<<(j-)))
{
++tot;
for(int k=;k<=x[j].size;++k)
{
int u=x[j].u[k],v=x[j].v[k];
a[u][u]++; a[v][v]++;
d[u][v]++; d[v][u]++;
}
}
for(int j=;j<=n;++j)
for(int k=;k<=n;++k) g[j][k]=a[j][k]-d[j][k];
if(n%==tot%) ans+=gauss();
else ans-=gauss();
ans=(ans%mod+mod)%mod;
}
ans=(ans%mod+mod)%mod;
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&n);
--n;
for(int i=;i<=n;++i)
{
scanf("%d",&x[i].size);
for(int j=;j<=x[i].size;++j) scanf("%d%d",&x[i].u[j],&x[i].v[j]);
}
// if(!n)
// {
// puts("1");
// return 0;
// }
solve();
return ;
}
 

bzoj 4596的更多相关文章

  1. BZOJ 4596: [Shoi2016]黑暗前的幻想乡

    Sol 容斥原理+Matrix-Tree定理.容斥跟小星星那道题是一样的,然后...直接Matrix-Tree定理就可以了... 复杂度\(O(2^{n-1}n^3)\) PS:调了好久啊QAQ 明明 ...

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

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

  3. ●BZOJ 4596 [Shoi2016]黑暗前的幻想乡

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4596 题解: 容斥,矩阵树定理,矩阵行列式 先说说容斥:(一共有 N-1个公司) 令 f[i ...

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

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

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

    真是简单粗暴 把矩阵树定理的运算当成黑箱好了反正我不会 这样我们就可以在O(n^3)的时间内算出一个无向图的生成树个数了 然后题目要求每个工程队选一条路,这里可以考虑容斥原理:全选的方案数-不选工程队 ...

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

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

  7. 【Learning】矩阵树定理 Matrix-Tree

    矩阵树定理 Matrix Tree ​ 矩阵树定理主要用于图的生成树计数. 看到给出图求生成树的这类问题就大概要往这方面想了. 算法会根据图构造出一个特殊的基尔霍夫矩阵\(A\),接着根据矩阵树定理, ...

  8. 生成树计数及应用 Matrix-Tree

    例:给定一个图,图上每条边是红色或蓝色 求恰好有K条红边的生成树的个数,N<=50. Matrix-Tree定理 对于限制条件可以利用多项式,把红边边权设为X,蓝边边权设为1. 最后求行列式得到 ...

  9. @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列

    目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...

随机推荐

  1. hdu 3879 最大密集子图(点和边均带权)(模板)

    /* 最大权闭合图,可以用最大密集子图来解速度更快复杂度低 题解:胡伯涛<最小割模型在信息学竞赛中的应用> 点和边均带权的最大密集子图 s-i,权为U=点权绝对值和+边的所有权值 i-t, ...

  2. 假面舞会(codevs 1800)

    题目描述 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会. 今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择 一个自己喜欢的面具.每个面具都有一 ...

  3. 【cmd】cmd常用命令

    dir 是英文单词directory(目录)的缩写,主要用来显示一个目录下的文件和子目录 md  是英文make directory(创建目录)的缩写 cd  是英文change directory( ...

  4. msp430项目编程27

    msp430中项目---多机通信系统 1.I2C工作原理 2.I2C通信协议 3.代码(显示部分) 4.代码(功能实现) 5.项目总结 msp430项目编程 msp430入门学习

  5. 关于Linux内核学习的一点点总结

    关于Linux内核学习的一点点总结 关键词:Linux, 操作系统,内核 博客列表 由反汇编C程序来理解计算机是如何工作的 通过分析一个简化版时间片轮转多道程序内核代码来认识操作系统中的进程调度 通过 ...

  6. ***ps -ef |grep 输出的具体含义是什么?

    Q: 比如:[root@localhost ~]# ps -ef | grep ApacheJetspeedroot 18887 18828 0 08:09 pts/0 00:00:00 grep A ...

  7. BNUOJ Eeny Meeny Moo

    Eeny Meeny Moo Time Limit: 1000ms Memory Limit: 65535KB                     大家都有这种经验,当太多的人同时使用互联网的时候 ...

  8. 从ASP.NET Core 3.0 preview 特性,了解CLR的Garbage Collection

    前言 在阅读这篇文章:Announcing Net Core 3 Preview3的时候,我看到了这样一个特性: Docker and cgroup memory Limits We conclude ...

  9. 学习MarkDown--初体验

    学习MarkDownPad 突然兴趣来了,在博客园里面也有Markdown的格式,昨天晚上安装了MarkDownPad pro这个是免费的,但是有些功能不支持.本来想破解的,百度了很多方法感觉不靠谱, ...

  10. Linux OpenSSH后门的加入与防范

    引言:相对于Windows,Linux操作系统的password较难获取.只是非常多Linuxserver配置了OpenSSH服务.在获取root权限的情况下,能够通过改动或者更新OpenSSH代码等 ...