首页 > 其他分享 >UOJ #37. [清华集训 2014] 主旋律

UOJ #37. [清华集训 2014] 主旋律

时间:2023-07-10 11:56:11浏览次数:53  
标签:连通 ed 37 typedef long UOJ 2014 define 分量

UOJ 传送门

考虑 dp。设 \(f_S\) 为点集 \(S\) 构成强连通分量的方案数。

容易想到容斥。设 \(ed_S\) 为 \(S\) 内部连边数,那么 \(f_S\) 就是总的方案数 \(2^{ed_S}\) 减去构成的不是强连通分量的方案数。

我们考虑如果整个图不是一个强连通分量,那么缩点后一定有 \(> 1\) 个分量,并且缩完点后图变成一个 DAG。

由此我们想到钦定 \(T \subseteq S\) 为点集 \(T\) 是入度为 \(0\) 的所有强连通分量点集的并集(注意这里 \(T\) 可以 \(= S\),因为可以有 \(> 1\) 个入度为 \(0\) 的强连通分量)。

但是这样会有算重,因为我们无法保证 \(T\) 中的分量就一定是全部入度为 \(0\) 的强连通分量。考虑容斥,容斥系数为 \((-1)^{cnt - 1}\),其中 \(cnt\) 为强连通分量个数,表示选奇数个强连通分量的系数为 \(+1\),偶数个为 \(-1\)。

设 \(g_T\) 为 \(T\) 中分成奇数个分量的方案数减去分成偶数个分量的方案数。容易转移:\(g_T = -\sum\limits_{w \subset T} f_w g_{T \setminus w}\)。注意这里我们钦定 \(w\) 包含 \(T\) 的最低位。

那么 \(f_S\) 就能转移了。设 \(h_T\) 为边 \(u \to v\) 的数量,其中 \(u \in S, v \in T\),那么这个东西可以递推求出。我们要限制其他点不能向 \(T\) 中的点连边,那么 \(f_S = 2^{ed_S} - \sum\limits_{T \subset S} 2^{ed_S - h_T} g_T\)。

code
// Problem: #37. 【清华集训2014】主旋律
// Contest: UOJ
// URL: https://uoj.ac/problem/37
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-(x)))
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 220;
const int maxm = (1 << 15) + 50;
const ll mod = 1000000007;

ll n, m, in[maxn], pw[maxn], f[maxm], g[maxm], h[maxm], ed[maxm], lg[maxm];
int stk[maxm], top;
pii E[maxn];

void solve() {
	scanf("%lld%lld", &n, &m);
	for (int i = 0; i < n; ++i) {
		lg[1 << i] = i;
	}
	pw[0] = 1;
	for (int i = 1; i < maxn; ++i) {
		pw[i] = pw[i - 1] * 2 % mod;
	}
	for (int i = 1, u, v; i <= m; ++i) {
		scanf("%d%d", &u, &v);
		--u;
		--v;
		in[v] |= (1 << u);
		E[i] = make_pair(u, v);
	}
	for (int S = 1; S < (1 << n); ++S) {
		for (int i = 1; i <= m; ++i) {
			int u = E[i].fst, v = E[i].scd;
			if ((S & (1 << u)) && (S & (1 << v))) {
				++ed[S];
			}
		}
	}
	for (int S = 1; S < (1 << n); ++S) {
		f[S] = pw[ed[S]];
		for (int T = S; T; T = (T - 1) & S) {
			stk[++top] = T;
		}
		while (top) {
			int T = stk[top--];
			h[T] = h[T ^ lowbit(T)] + __builtin_popcount(in[lg[lowbit(T)]] & S);
		}
		for (int T = (S - 1) & S; T; T = (T - 1) & S) {
			if (T & lowbit(S)) {
				g[S] = (g[S] - f[T] * g[S ^ T] % mod + mod) % mod;
			}
		}
		for (int T = S; T; T = (T - 1) & S) {
			f[S] = (f[S] - pw[ed[S] - h[T]] * g[T] % mod + mod) % mod;
		}
		g[S] = (g[S] + f[S]) % mod;
	}
	printf("%lld\n", f[(1 << n) - 1]);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:连通,ed,37,typedef,long,UOJ,2014,define,分量
From: https://www.cnblogs.com/zltzlt-blog/p/17540655.html

相关文章

  • 山东大学考研机试--AcWing 3717. 整数序列
    题目描述很多整数可以由一连串的整数序列(至少两个数)相加而成,比如25=3+4+5+6+7=12+13。输入一个整数N,输出N的全部整数序列,如果没有则输出NONE。输入格式一个整数N。输出格式每行输出一个满足条件的整数序列。序列内部元素从小到大排序。优先输出首项更小的序列。数据......
  • 洛谷 P3378 【模板】堆
    siftup模板当然还得有siftdown模板“稍”加调试,就可以得到模板代码#include<bits/stdc++.h>usingnamespacestd;intn,op,sl=0,h[1000010];voidjh(intx,inty)//交换{intz=h[x];h[x]=h[y];h[y]=z;}voidsiftu(inti)//siftup{boolf=true;......
  • P3378 【模板】二叉堆
    [洛谷]P3378【模板】堆方法一手写堆最小堆插入从新增的最后一个结点的父结点开始,用要插入元素向下过滤上层结点(相当于要插入的元素向上渗透)voidsiftdown(inti)//传入一个需要向下调整的结点编号i,这里传入1,即从堆的顶点开始向下调整{intt,flag=0;//flag用来标......
  • 一文彻底搞懂MySQL基础:B树和B+树的区别 转载 https://blog.csdn.net/a519640026/arti
    写在前面大家在面试的时候,肯定都会被问到MySql的知识,以下是面试场景:面试官:对于MySQL,你对他索引原理了解吗?我:了解面试官:MySQL的索引是用什么数据机构的?我:B+树面试官:为什么要用B+树,而不是B树?我:…面试官:用B+树作为MySql的索引结构,用什么好处?我:…B树和B+树是MySQL索引使用的数据结构......
  • Docker开启远程端口访问2375
    开启方法:1、修改/etc/default/docker下的配置cat>>/etc/default/docker<<EOFDOCKER_OPTS="-Htcp://0.0.0.0:2375"EOFsystemctlrestartdocker2、修改/usr/lib/systemd/system/docker.service配置cat>>/usr/lib/systemd/system/docker.service<......
  • https://www.zhihu.com/tardis/bd/art/627016379?source_id=1001
    1、ODS原始数据层ODS层保存所有操作数据,不对原始数据做任何处理。在业务系统和数据仓库之间形成一个隔离,源系统数据结构的变化不影响其他数据分层。减轻业务系统被反复抽取的压力,由ODS统一进行抽取和分发。记住ODS层数据要保留数据的原始性。处理原则:根据源业务系统表的情况以......
  • 6537: candy买糖果 桶排序
    描述  candy非常喜欢吃糖果,于是他就攒下平时妈妈发的零花钱,准备放学后去偷偷买糖。现在candy知道自己的存钱罐里一共有n张纸币,每张纸币的面值为Vi。这几天放学后,他想要用这些钱买m种糖果,并且希望能用一种面值的纸币恰好买到所有的糖果。  输入  第一行包含两个......
  • GDAL源码剖析与开发指南 - 李民录 - 2014
    本书适合地理信息系统和遥感等相关专业应用的开发人员阅读参考。本书中大部分的示例代码都是使用C/C++语言编写,有一定C/C++语言基础的读者能够快速上手开发相关应用。目录第1章GDAL简介.................1第2章OGR空间参考.............42第3章OGR库说明........................
  • 【树状数组】 HDOJ 3743 Frosh Week
    简单的树状数组求逆序数,不过要用到离散化。。。。刚开始没用离散化,就跪了。。#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#in......
  • POJ 3728 The merchant
    题意好像不清楚:给定一棵\(n​\)个点的树,每个点有点权\(val_i​\),现在有\(q​\)个询问,每次询问给出\(u,v​\),设\(u​\)到\(v​\)的路径上的点编号为\(a_1,a_2\cdotsa_{len}​\),求\(\max\limits_{1\lex<y\lelen}{val_{a_y}-val_{a_x}}​\)。因为\(x,y\)有顺......