题目

这可算是一道非常好的关于容斥原理的题了。

算法

好吧,这题我毫无思路,直接给正解。

首先,问题的正面不容易求,那么就求反面吧:

有多少种添加边的方案,使得这个图是DAG图(这里及以下所说的DAG图都是指这个图不是整个强连通的)。

利用容斥原理,DAG图的特征是有至少一个入度为\(0\)的点并且这个图不止一个点(这里及以下所说的点都是指求强连通后的点),就根据这个进行容斥。

设\(g(set)\)为集合里的点都是入度为\(0\)的方案数,注意,这个有点特别,比如这个:

它的值应该为\(0\)。虽然有两种方案,一种是两条边都添加,另一种是都不添加。但是,都不添加的话,由于两个点(偶数个点),系数应该是负的!!所以\(g(set) = (-1) + (1) = 0\)。

设\(f(set)\)为有多少种添加边的方案,使得整个图强连通。

好吧,我真的不知道怎样说清楚。-_-|||。不过看了代码应该就很清楚了。。。

这里的\(h(set)\)是这些点的诱导子图有多少条边。

至于时间复杂度,就是$$O(\sum_{i=0}{n}{Ci_n\cdot 2^i})$$

根据二次项定理可知时间复杂度为\(O(3^n)\)。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <assert.h>
using namespace std; #ifdef debug
#define ep(...) fprintf(stderr, __VA_ARGS__)
#else
#define ep(...) assert(true)
#endif template <class T>
void relax(T &a, const T &b)
{
if (b > a) a = b;
} template <class T>
void tension(T &a, const T &b)
{
if (b < a) a = b;
} typedef long long i64; const int MaxN = 15;
const int MaxSet = (1 << MaxN) + 3;
const int MOD = (int) 1e9 + 7; int main()
{
#if defined(debug) || defined(local)
freopen("in", "r", stdin);
freopen("out", "w", stdout);
#endif int n, m;
scanf("%d%d", &n, &m); static int in[MaxSet], out[MaxSet];
for (int i = 0; i < m; i ++)
{
int u, v;
scanf("%d%d", &u, &v);
u --, v --;
in[1 << v] |= 1 << u;
out[1 << u] |= 1 << v;
} static int cnt[MaxSet], power2[MaxSet];
power2[0] = 1;
for (int i = 1; i < 1 << n; i ++)
{
cnt[i] = cnt[i ^ (i & -i)] + 1;
power2[i] = power2[i - 1] << 1;
if (power2[i] >= MOD) power2[i] -= MOD;
} static int f[MaxSet], g[MaxSet], h[MaxSet];
for (int i = 1; i < 1 << n; i ++)
{
if (cnt[i] == 1)
{
f[i] = g[i] = 1;
h[i] = 0;
continue;
}
int u = i & -i; h[i] = h[i ^ u] + cnt[out[u] & i] + cnt[in[u] & i]; for (int sub = (i - 1) & i; sub; sub = (sub - 1) & i)
if (sub & u)
{
g[i] = ((i64) g[i] + MOD - (i64) g[i ^ sub] * f[sub]) % MOD;
} static int w[MaxSet];
int rev_f = 0;
for (int sub = i; sub; sub = (sub - 1) & i)
{
if (sub == i)
{
w[sub] = 0;
}
else
{
int v = (i ^ sub) & -(i ^ sub);
w[sub] = w[sub ^ v] - cnt[out[v] & (i ^ sub)] + cnt[in[v] & sub];
}
rev_f = ((i64) rev_f + (i64) g[sub] * power2[h[i ^ sub] + w[sub]]) % MOD;
}
f[i] = (power2[h[i]] + MOD - rev_f) % MOD; ep("tmp_g: %d\n", g[i]);
g[i] = (g[i] + f[i]) % MOD; ep("%d: %d %d %d\n", i, f[i], g[i], h[i]);
}
cout << f[(1 << n) - 1] << endl;
ep("answer %d", f[(1 << n) - 1]); return 0;
}

清华集训2014 day1 task2 主旋律的更多相关文章

  1. 清华集训2014 day1 task1 玛里苟斯

    题目 这可算是描述很简单的一道题了!但是不简单. \(S\)是一个可重集合,\(S = \{a_1, a_2, \dots, a_n \}\). 等概率随机取\(S\)的一个子集\(A = \{a_{ ...

  2. 清华集训2014 day1 task3 奇数国

    题目 题目看起来好像很难的样子!其实不然,这是最简单的一道题. 算法 首先要注意的是: \(number \cdot x + product \cdot y = 1\) ,那么我们称\(number\ ...

  3. uoj 41 【清华集训2014】矩阵变换 婚姻稳定问题

    [清华集训2014]矩阵变换 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/41 Description 给出 ...

  4. AC日记——【清华集训2014】奇数国 uoj 38

    #38. [清华集训2014]奇数国 思路: 题目中的number与product不想冲: 即为number与product互素: 所以,求phi(product)即可: 除一个数等同于在模的意义下乘 ...

  5. UOJ#46. 【清华集训2014】玄学

    传送门 分析 清华集训真的不是人做的啊嘤嘤嘤 我们可以考虑按操作时间把每个操作存进线段树里 如果现在点x正好使一个整块区间的右端点则更新代表这个区间的点 我们不难发现一个区间会因为不同的操作被分成若干 ...

  6. 清华集训2014 sum

    清华集训2014sum 求\[∑_{i=1}^{n}(-1)^{⌊i√r⌋}\] 多组询问,\(n\leq 10^9,t\leq 10^4, r\leq 10^4\). 吼题解啊 具体已经讲得很详细了 ...

  7. UOJ#37. 【清华集训2014】主旋律

    题目大意: 传送门 题解: 神题……Orz. 首先正难则反. 设$f_S$表示选取点集状态为s时,这部分图可以构成非强联通图的方案数. 设$p_{S,i}$表示点集s缩点后有i个入度为0点的方案数,保 ...

  8. [清华集训2015 Day1]主旋律-[状压dp+容斥]

    Description Solution f[i]表示状态i所代表的点构成的强连通图方案数. g[i]表示状态i所代表的的点形成奇数个强连通图的方案数-偶数个强连通图的方案数. g是用来容斥的. 先用 ...

  9. 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理

    题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum ...

随机推荐

  1. BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会( dp + dfs )

    选取任意一个点为root , size[ x ] 表示以 x 为根的子树的奶牛数 , dp一次计算出size[ ] && 选 root 为集会地点的不方便程度 . 考虑集会地点由 x ...

  2. BZOJ 1572: [Usaco2009 Open]工作安排Job( 贪心 )

    贪心... 按截止时间排序 , 然后从小到大考虑 . 假设当前考虑第 i 个任务 , 若目前已选工作数 < D_i , 那就选 i ; 否则 若已选工作中利润最小的比 P_i 小 , 那就去除它 ...

  3. 安装Oracle,新建组、用户的时候的一个错误

    [root@localhost /]# mkdir -p /u01/oracle[root@localhost /]# useradd -g oinstall -G dba -d /u01/oracl ...

  4. django开发简易博客(五)

    这一节将讲述如何添加comments库与ajax的支持. 一.添加comments库 comments库是是django框架内置的一个评论库,可以快速的搭建岀一个评论系统,不过再自定义方面有些麻烦,不 ...

  5. QT无标题窗口在任务栏显示关闭(增加系统菜单)

    在对话框中使用了如下代码: setWindowFlags(Qt::FramelessWindowHint); 在任务栏上右键点击程序,不会弹出菜单,解决办法,使用下面代码: setWindowFlag ...

  6. CSS块元素与内联元素(转)

    为什么<a><span>这种标签定义width,height等CSS属性时会发现完全不生效? 因为它们不是容器,它们是内联元素,不是块元素 CSS 块元素与内联元素 关键字: ...

  7. Effective C++:条款37:绝不又一次定义继承而来的缺省參数值

    因为又一次定义继承而来的non-virtual函数是不对的(见上一个条款),所以这个条款就将问题局限于:绝不又一次定义继承一个带有缺省參数值的virtual函数. (一) virtual函数是动态绑定 ...

  8. [转]组合数取模 Lucas定理

    对于C(n, m) mod p.这里的n,m,p(p为素数)都很大的情况.就不能再用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式递推了. 这里用到Lusac定理 ...

  9. 【centos6 , 6】linux 查看帮助文档:

    1. 使用   命令 -h 或 命令 --help ,  例: ls -h 2. man命令  : man  命令              例:man ls 3.info命令:           ...

  10. Android 中 关闭部分 Activity 的方法总结

    每一个activity都有自己的生命周期,被打开了最终就要被关闭. 四种结束当前的activity方法 但如果已经启动了四个Activity:A,B,C和D, 在D Activity里,想再启动一个A ...