题面

Description

定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与

G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中, 否则这条边不在 G 中.

现在给定 s 个结点数相同的图 G1...s, 设 S = {G1, G2, . . . , Gs}, 请问 S 有多少个子集的异

或为一个连通图?

Input

第一行为一个整数s, 表图的个数.

接下来每一个二进制串, 第 i 行的二进制串为 gi, 其中 gi 是原图通过以下伪代码转化得

到的. 图的结点从 1 开始编号, 下面设结点数为 n.

Algorithm 1 Print a graph G = (V, E)

for i = 1 to n do

for j = i + 1 to n do

if G contains edge (i, j) then

print 1

else

print 0

end if

end for

end for

2 ≤ n ≤ 10,1 ≤ s ≤ 60.

Output

输出一行一个整数, 表示方案数

Sample Input

3

1

1

0

Sample Output

4

题解

容斥+线性基+DFS

(其中我最不会的居然是DFS! TAT)

要求异或图连通,不会。

考虑容斥。

将n个点分为x组,然后求连通性“至少”是当前分组情况的方案数——什么是“至少”呢?不同组的点之间一定不连通,相同组的点之间可以连通也可以不连通。

这样,最终答案就是:所有分成一组的方案数 - 所有分成两组的 + 所有分成三组的……

n个点分成任意大小组的所有方案都可以DFS枚举出来。

那么已知一种分组方案,如何求有多少图的集合的异或图(原题里提到的那个)满足“不同组的点之间一定不连通”呢?

把每对有要求限制的点对(即不同组之间的点对)用一个二进制位表示, 如果某个图中有这条边,则这一位是1,否则为0,就用一个二进制数表示了一个图。

现在要求的就是有多少个图的集合(即二进制数的集合)异或和是0,即在异或图上所有有限制的点对都不存在对应的边。

怎么求呢?用线性基,集合个数就是\(2^{图的数量 - 线性基大小}\)。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
} const int N = 11, M = 61;
char s[N*N];
bool conn[M][N][N];
int n, m, bel[N];
ll fac[N], lb[M], ans; void dfs(int u, int x){
if(u > n){
int sze = 0;
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
if(bel[i] != bel[j]){
ll val = 0;
for(int k = 1; k <= m; k++)
if(conn[k][i][j]) val |= 1LL << (k - 1);
for(int k = 1; k <= sze; k++)
if((val ^ lb[k]) < val) val ^= lb[k];
if(val) lb[++sze] = val;
}
ans += fac[x] * (1LL << (m - sze));
return;
}
for(int i = 1; i <= (x + 1); i++)
bel[u] = i, dfs(u + 1, x + (i > x));
} int main(){ read(m);
for(int k = 1; k <= m; k++){
scanf("%s", s + 1);
if(!n)
for(int i = 1, len = strlen(s + 1); !n; i++)
if(i * (i - 1) / 2 == len)
n = i;
for(int i = 1, p = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
conn[k][i][j] = s[p++] - '0';
}
fac[1] = 1;
for(int i = 2; i <= n; i++)
fac[i] = fac[i - 1] * (1 - i);
dfs(1, 0);
write(ans), enter; return 0;
}

BZOJ 4671 异或图 | 线性基 容斥 DFS的更多相关文章

  1. bzoj 4671 异或图——容斥+斯特林反演+线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671 考虑计算不是连通图的方案,乘上容斥系数来进行容斥. 可以枚举子集划分(复杂度是O(Be ...

  2. bzoj 4671 异或图 —— 容斥+斯特林反演+线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671 首先,考虑容斥,就是设 \( t[i] \) 表示至少有 \( i \) 个连通块的方 ...

  3. 【XSY2701】异或图 线性基 容斥原理

    题目描述 定义两个图\(G_1\)与\(G_2\)的异或图为一个图\(G\),其中图\(G\)的每条边在\(G_1\)与\(G_2\)中出现次数和为\(1\). 给你\(m\)个图,问你这\(m\)个 ...

  4. [BZOJ 4671]异或图

    Description 题库链接 给定 \(s\) 个结点数相同且为 \(n\) 的图 \(G_1\sim G_s\) ,设 \(S = \{G_1, G_2,\cdots , G_s\}\) ,问 ...

  5. 【BZOJ】4671: 异或图

    题解 写完之后开始TTTTTTT--懵逼 这道题我们考虑一个东西叫容斥系数啊>< 这个是什么东西呢 也就是\(\sum_{i = 1}^{m}\binom{m}{i}f_{i} = [m ...

  6. bzoj 2115 [Wc2011] Xor 路径最大异或和 线性基

    题目链接 题意 给定一个 \(n(n\le 50000)\) 个点 \(m(m\le 100000)\) 条边的无向图,每条边上有一个权值.请你求一条从 \(1\)到\(n\)的路径,使得路径上的边的 ...

  7. BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]

    4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...

  8. 51Nod1577 异或凑数 线性基 构造

    国际惯例的题面:异或凑出一个数,显然是线性基了.显然我们能把区间[l,r]的数全都扔进一个线性基,然后试着插入w,如果能插入,则说明w不能被这些数线性表出,那么就要输出"NO"了. ...

  9. 【loj114】k大异或和 线性基+特判

    题目描述 给由 $n​$ 个数组成的一个可重集 $S​$ ,每次给定一个数 $k​$ ,求一个集合 $T⊆S​$ ,使得集合 $T​$ 在 $S​$ 的所有非空子集的不同的异或和中,其异或和 $T_1 ...

随机推荐

  1. VM下设置CenOS为静态IP

    在本机利用VM启动了4台虚拟机来搭建zookeeper集群,但是每次电脑重启后,虚拟机的IP都会变化,现在想来固定每台虚拟机的IP. 1.Step1:查看网关和子网掩码 记住选用NAT模式,点击NAT ...

  2. .NET持续集成与自动化部署之路第一篇——半天搭建你的Jenkins持续集成与自动化部署系统

    .NET持续集成与自动化部署之路第一篇(半天搭建你的Jenkins持续集成与自动化部署系统) 前言     相信每一位程序员都经历过深夜加班上线的痛苦!而作为一个加班上线如家常便饭的码农,更是深感其痛 ...

  3. gist.github.com 被墙无法访问解决办法

    windows下 打开C:\Windows\System32\drivers\etc\hosts文件 编辑器打开,在最后行添加192.30.253.118 gist.github.com 保存.

  4. 【转载】固态硬盘的S.M.A.R.T详解

    文章来源于: 瑞耐斯存储技术 兵哥写这篇文章,是因为在测试的过程中看到了 SSD存在偶尔有性能下降的情况,经分析为S.M.A.R.T命令所导致,虽然这种情况看似不严重,但如果应用在诸如数据采集等关键性 ...

  5. 一个高性能的对象属性复制类,支持不同类型对象间复制,支持Nullable<T>类型属性

    由于在实际应用中,需要对大量的对象属性进行复制,原来的方法是通过反射实现,在量大了以后,反射的性能问题就凸显出来了,必须用Emit来实现. 搜了一圈代码,没发现适合的,要么只能在相同类型对象间复制,要 ...

  6. Rabbit and Grass

    链接 [http://acm.hdu.edu.cn/showproblem.php?pid=1849] 题意 大学时光是浪漫的,女生是浪漫的,圣诞更是浪漫的,但是Rabbit和Grass这两个大学女生 ...

  7. 12.11 Daily Scrum

      Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐厅列表. 实现和菜谱相关的餐厅列表.             邓亚梅             美化搜索框UI. 美 ...

  8. Linux内核分析第五周学习总结

    扒开系统调用的三层皮(下) 20135237朱国庆+ 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/UST ...

  9. Python学习笔记 -- 第五章

    模块 使用模块可以提高了代码的可维护性.其次,编写代码不必从零开始.当一个模块编写完毕,就可以被其他地方引用.我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块: ...

  10. java感想

    Java学起来很有趣,通过学习Java可以提高自己的逻辑能力.在学习Java期间我们做了一些程序,我们班的同学也都积极准备,完成的还不错!在做程序时,我遇到了一些难题,有时也会出现错误,时间长了弄得我 ...