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. bzoj 1703 [Usaco2007 奶牛排名 传递闭包

    [Usaco2007 Mar]Ranking the Cows 奶牛排名 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 504  Solved: 343[ ...

  2. [NOIP2003] 提高组 洛谷P1038 神经网络

    题目背景 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别.函数逼近及贷款风险评估等诸多领域有广泛的应用.对神经网络的研究一直是当今 ...

  3. 《TCP/IP详解卷1:协议》——第6章 ICMP:Internet控制报文协议(转载)

    1.引言 ICMP被认为是IP层的一个组成部分,它传递差错报文以及其他需要注意的信息.ICMP报文通常被IP层或更高层协议(TCP或UDP)使用.一些ICMP报文把差错报文返回给用户进程. ICMP报 ...

  4. [Bzoj2039]小Z的袜子 (莫队算法模板题)

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 11866  Solved: 5318[Sub ...

  5. 寒武纪camp Day5

    补题进度:6/10 A(状压dp) 题意: 有n个数字1,2,...,n,有m个限制(a,b),表示至少要有一个数字a排在数字b的前面 你需要构造出一个含有数字1~n的序列,数字可以重复多次,要求该序 ...

  6. linux是类unix操作系统

    linux是类unix操作系统,linux与unix使用的基础命令是一样的,没有区别.Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程 ...

  7. 【C++基础 02】深拷贝和浅拷贝

    我的主题是.每天积累一点点. =========================================== 在类定义中,假设没有提供自己的拷贝构造函数,则C++提供一个默认拷贝构造函数. C ...

  8. iOS macOS的后渗透利用工具:EggShell

    EggShell是一款基于Python编写的iOS和macOS的后渗透利用工具.它有点类似于metasploit,我们可以用它来创建payload建立侦听.此外,在反弹回的session会话也为我们提 ...

  9. 实例 mount新硬盘方法

    0.建立挂载文件夹: mkdir /mnt/sdb1 1 .查看新硬盘: fdisk -l 2. 硬盘分区: fdisk /dev/sdb1 根据提示,依次输入 n, p, 1, 以及两次回车,然后是 ...

  10. input 文本框禁止输入表情

    js在用户输入表情时自动过滤掉 <input type="text" id="input" maxlength="10"/> v ...