题解

我一开始写的最小表示法写的插头dp,愉快地TLE成60分

然后我觉得我就去看正解了!

发现是容斥 + 矩阵树定理

矩阵树定理对于有重边的图只要邻接矩阵的边数设置a[u][v]表示u,v之间有几条边就好

我们枚举哪些公司不用,然后用矩阵树求一下生成几棵树,复杂度\(2^{n - 1}(n - 1)^3\)

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
#define pb push_back
#define MAXN 200005
#define mo 974711
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 - '0' + c;
c = getchar();
}
res = res * f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N,cnt[(1 << 17) + 5],D[18][18],len[25];
pii E[25][505];
int lowbit(int x) {
return x & (-x);
}
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
void Init() {
read(N);
int M,u,v;
for(int i = 1 ; i < N ; ++i) {
read(M);len[i] = M;
for(int j = 1 ; j <= M ; ++j) {
read(u);read(v);
E[i][j] = mp(u,v);
}
}
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
int Guass() {
int res = 1;
for(int i = 2 ; i <= N ; ++i) {
int l = i;
if(!D[l][i]) {
for(int j = i + 1 ; j <= N ; ++j) {
if(D[j][i]) {l = j;break;}
}
}
if(!D[l][i]) return 0;
if(l != i) {
res = -res;
for(int j = i ; j <= N ; ++j) swap(D[l][j],D[i][j]);
}
for(int j = i + 1; j <= N ; ++j) {
int t = mul(D[j][i],fpow(D[i][i],MOD - 2));
for(int k = i ; k <= N ; ++k) {
D[j][k] = inc(D[j][k],MOD - mul(D[i][k],t));
}
}
}
if(res == -1) res = MOD - 1;
for(int i = 2 ; i <= N ; ++i) {
res = mul(res,D[i][i]);
}
return res;
}
int calc(int S) {
memset(D,0,sizeof(D));
for(int i = 1 ; i <= N - 1; ++i) {
if(S >> (i - 1) & 1) {
for(int j = 1 ; j <= len[i] ; ++j) {
D[E[i][j].fi][E[i][j].se] -= 1;
D[E[i][j].se][E[i][j].fi] -= 1;
D[E[i][j].fi][E[i][j].fi]++;
D[E[i][j].se][E[i][j].se]++;
}
}
}
for(int i = 2 ; i <= N; ++i) {
if(!D[i][i]) return 0;
for(int j = 2 ; j <= N ; ++j) {
D[i][j] = inc(D[i][j],MOD);
}
}
return Guass();
}
void Solve() {
int ans = 0;
for(int S = 0 ; S < (1 << (N - 1)) ; ++S) {
if(S) cnt[S] = cnt[S - lowbit(S)] + 1;
if((N - 1 - cnt[S]) & 1) ans = inc(ans,MOD - calc(S));
else ans = inc(ans,calc(S));
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}

【LOJ】#2027. 「SHOI2016」黑暗前的幻想乡的更多相关文章

  1. 「SHOI2016」黑暗前的幻想乡 解题报告

    「SHOI2016」黑暗前的幻想乡 sb题想不出来,应该去思考原因,而不是自暴自弃 一开始总是想着对子树做dp,但是状态压不起去,考虑用容斥消减一些条件变得好统计,结果越想越乱. 期间想过矩阵树定理, ...

  2. 「SHOI2016」黑暗前的幻想乡

    题目链接 戳我 \(Describe\) \(n−1\)个公司,每个公司能修一些边,求每条边都让不同的公司来修的生成树的方案数 \(Solution\) 这道题很明显容斥.答案就是:所有都选的生成树个 ...

  3. loj2027 「SHOI2016」黑暗前的幻想乡

    矩阵树定理+模意义下整数高斯消元 #include <algorithm> #include <iostream> #include <cstring> #incl ...

  4. Solution -「SHOI2016」「洛谷 P4336」黑暗前的幻想乡

    \(\mathcal{Description}\)   link.   有一个 \(n\) 个结点的无向图,给定 \(n-1\) 组边集,求从每组边集选出恰一条边最终构成树的方案树.对 \(10^9+ ...

  5. 【SHOI2016】黑暗前的幻想乡

    题面 题解 如果没有建筑公司的限制,那么就是个\(\mathrm{Matrix\;tree}\)板子 其实有了也一样 发现\(n\leq 17\),考虑容斥 每次钦定一些建筑公司,计算它们包含的边的生 ...

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

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

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

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

  8. [ZJOI2016]小星星&[SHOI2016]黑暗前的幻想乡(容斥)

    这两道题思路比较像,所以把他们放到一块. [ZJOI2016]小星星 题目描述 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星. ...

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

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

随机推荐

  1. Hadoop基础-序列化与反序列化(实现Writable接口)

    Hadoop基础-序列化与反序列化(实现Writable接口) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.序列化简介 1>.什么是序列化 序列化也称串行化,是将结构化 ...

  2. [2009国家集训队]小Z的袜子(hose) 浅谈莫队

    浅谈莫队 推荐学习博客 http://foreseeable97.logdown.com/posts/158522-233333 借用题目: bzoj 2038 2009 国家集训队 小Z的袜子htt ...

  3. python 操作excel格式化及outlook正文,发送邮件

    import requests import time import os import arrow import pandas as pd import pandas.io.formats.exce ...

  4. 【leetcode 简单】 第九十七题 快乐数

    写一个程序,输出从 1 到 n 数字的字符串表示. 1. 如果 n 是3的倍数,输出“Fizz”: 2. 如果 n 是5的倍数,输出“Buzz”: 3.如果 n 同时是3和5的倍数,输出 “FizzB ...

  5. HDU 3065 病毒侵袭持续中 (AC自动机)

    题目链接 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒 ...

  6. J - Clairewd’s message HDU - 4300(扩展kmp)

    题目链接:https://cn.vjudge.net/contest/276379#problem/J 感觉讲的很好的一篇博客:https://subetter.com/articles/extend ...

  7. [转]编译防火墙——C++的Pimpl惯用法解析

    impl(pointer to implementation, 指向实现的指针)是一种常用的,用来对“类的接口与实现”进行解耦的方法.这个技巧可以避免在头文件中暴露私有细节(见下图1),因此是促进AP ...

  8. spring-boog-测试打桩-Mockito

    Mockito用于测试时进行打桩处理:通过它可以指定某个类的某个方法在什么情况下返回什么样的值. 例如:测试 controller时,依赖 service,这个时候就可以假设当调用 service 某 ...

  9. HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意:n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V ...

  10. 05 Go 1.5 Release Notes

    Go 1.5 Release Notes Introduction to Go 1.5 Changes to the language Map literals The Implementation ...