@description@

给定一个 n 点 m 边的无向图。

现在要求给每个点写上 0 或 1,一条边的权值定义为该边连接的两点权值之和。

有多少种方案,使得存在至少一条边的权值为 0,至少一条边权值为 1,至少一条边权值为 2。

Input

第一行包含两个数 n 和 m (1≤n≤40, 0≤m≤n*(n−1)/2),表示点数与边数。

接下来 m 行,每行两个整数 xi 与 yi (1≤xi,yi≤n, xi≠yi),描述一条边的两个端点。

保证无重边。

Output

输出合法的方案个数。

Examples

input

6 5

1 2

2 3

3 4

4 5

5 1

output

20

input

4 4

1 2

2 3

3 4

4 1

output

4

@solution@

n <= 40 暗示 meet in the middle。要求的计数方案暗示容斥。

首先考虑怎么容斥,我们统计以下方案数量:

f1:没有任何限制。

f2:强制 0 不出现。

f3:强制 1 不出现。

f4:强制 2 不出现。

f5:强制 0 与 1 不出现。

f6:强制 0 与 2 不出现。

f7:强制 1 与 2 不出现。

f8:强制 0, 1 与 2 不出现。

最终答案 ans = f1 - f2 - f3 - f4 + f5 + f6 + f7 - f8。

接下来考虑具体怎么计数。

首先易得 f1 = 2^n。

如果所有连通分量大小都为 1,共有 m 个连通分量,则 f8 = 2^m;否则 f8 = 0。

如果所有连通分量都为二分图,共有 m 个连通分量,则 f6 = 2^m;否则 f6 = 0。

如果大小为 1 的连通分量个数为 k,则 f5 = f7 = 2^k。

如果总连通分量个数为 m,则 f3 = 2^m。

而剩下的 f2, f4 就需要双向搜索。因为 f2 = f4,我们不妨只考虑 f4。

假如点 u 的数值为 0,则它相邻的点不带限制;否则如果点 u 的数值为 1,它相邻的点只能为 0。

我们枚举前一半的二进制状态,得到哪些点必须为 0,进而判断当前状态是否合法。

记 f[s] 表示 s 是否合法,合法为 1,否则为 0;g[s] 表示二进制 s' <= s 的 f[s'] 之和,高维前缀和即可。

查询时枚举后一半的二进制状态,首先判断是否合法,然后得到前一半哪些为 0,哪些为 0 或 1。直接取 g 值即可。

@accepted code@

#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
int n, m; ll G[40 + 5];
int fa[40 + 5], siz[40 + 5];
int find(int x) {
return fa[x] = (fa[x] == x ? x : find(fa[x]));
}
void unite(int x, int y) {
int fx = find(x), fy = find(y);
if( fx != fy ) fa[fx] = fy, siz[fy] += siz[fx];
}
ll check(int x) {
ll d[40 + 5] = {};
for(int i=0;i<n;i++)
d[i] = -1;
queue<int>que; que.push(x); d[x] = 0;
while( !que.empty() ) {
int f = que.front(); que.pop();
for(int i=0;i<n;i++)
if( (G[f]>>i) & 1 ) {
if( d[i] == -1 ) {
d[i] = d[f] ^ 1;
que.push(i);
}
else {
if( d[i] != (d[f] ^ 1) )
return 0;
}
}
}
return 2;
}
ll solve1() {
ll ret1 = 1, ret2 = 1, ret3 = 1, ret4 = 1;
for(int i=0;i<n;i++)
if( fa[i] == i ) {
ret1 <<= 1;
ret2 = ret2*check(i);
ret3 = (siz[i] == 1) ? (ret3<<1) : ret3;
ret4 = (siz[i] == 1) ? (ret4<<1) : 0;
}
return ret2 - ret1 + (ret3<<1) - ret4;
}
ll f[1<<20];
void dfs1(int d, int mxd, int s1, int s2) {
if( d == mxd ) {
f[s1]++;
return ;
}
dfs1(d + 1, mxd, s1, s2);
if( !(s2 & (1LL<<d)) )
dfs1(d + 1, mxd, s1|(1LL<<d), s2|G[d]);
}
int mid, t;
ll dfs2(int d, int mxd, ll s) {
if( d == mxd ) {
s = s & t, s = s ^ t;
return f[s];
}
ll ret = dfs2(d + 1, mxd, s);
if( !(s & (1LL<<d)) )
ret += dfs2(d + 1, mxd, s|G[d]);
return ret;
}
ll solve2() {
mid = (n>>1), t = (1<<mid) - 1;
dfs1(0, mid, 0, 0);
for(int i=0;i<mid;i++)
for(int j=0;j<=t;j++)
if( j & (1LL<<i) ) f[j] += f[j^(1LL<<i)];
return dfs2(mid, n, 0);
}
int main() {
scanf("%d%d", &n, &m);
for(int i=0;i<n;i++) fa[i] = i, siz[i] = 1;
for(int i=1;i<=m;i++) {
int x, y; scanf("%d%d", &x, &y), x--, y--;
G[x] |= (1LL<<y), G[y] |= (1LL<<x), unite(x, y);
}
printf("%lld\n", (1LL<<n) + solve1() - (solve2()<<1));
}

@details@

一开始没有考虑到连通块大小为 1(即该连通块中没有边)的情况,WA 了一次。

然后因为没开 long long,WA 了好几次。

@codeforces - 1221G@ Graph And Numbers的更多相关文章

  1. [codeforces 55]D. Beautiful numbers

    [codeforces 55]D. Beautiful numbers 试题描述 Volodya is an odd boy and his taste is strange as well. It ...

  2. Codeforces 1221 G Graph And Numbers

    题面 这种比赛时只有11个人做出来的题一般来说都是暴难的, 我也不知道我怎么搞出来的www 看完这个题第一感觉就是要容斥,至少有一条某种边的方案已经比较难求了,而直接算三种边都至少存在一条的方案数就更 ...

  3. CodeForces - 1245A Good ol' Numbers Coloring (思维)

    Codeforces Round #597 (Div. 2 Consider the set of all nonnegative integers: 0,1,2,-. Given two integ ...

  4. CodeForces 682A Alyona and Numbers (水题)

    Alyona and Numbers 题目链接: http://acm.hust.edu.cn/vjudge/contest/121333#problem/A Description After fi ...

  5. Codeforces 449D Jzzhu and Numbers

    http://codeforces.com/problemset/problem/449/D 题意:给n个数,求and起来最后为0的集合方案数有多少 思路:考虑容斥,ans=(-1)^k*num(k) ...

  6. Codeforces gym101612 E.Equal Numbers(贪心)

    传送:http://codeforces.com/gym/101612 题意:给出一个大小为n的序列a[i],每次选其中一个数乘以一个正整数,问进行k步操作后最少剩下多少种数字,输出0≤k≤n,所有的 ...

  7. Codeforces 817C Really Big Numbers - 二分法 - 数论

    Ivan likes to learn different things about numbers, but he is especially interested in really big nu ...

  8. Codeforces 405E Graph Cutting

    Graph Cutting 不会写.. dfs的过程中把回边丢到它的祖先中去, 回溯的时候两两配对.感觉好神奇啊. #include<bits/stdc++.h> #define LL l ...

  9. Codeforces 449D Jzzhu and Numbers(高维前缀和)

    [题目链接] http://codeforces.com/problemset/problem/449/D [题目大意] 给出一些数字,问其选出一些数字作or为0的方案数有多少 [题解] 题目等价于给 ...

随机推荐

  1. spring cloud深入学习(二)-----服务注册中心spring cloud eureka

    服务治理 主要用来实现各个微服务实例的自动化注册与发现,为啥需要这玩意呢?在一开始比如A系统调用B服务,可能通过手工维护B服务的实例,并且还得采用负载均衡等方式,这些全部都得需要手工维护,等后面系统越 ...

  2. Mac系统常用快捷键大全

    苹果Mac系统常用快捷键有很多,但是很多童鞋对于这些mac快捷键都不是很熟悉,今天小编为大家整理了一份Mac系统常用快捷键大全,大家快收藏起来吧!平时在使用mac系统的时候可以提高不少工作效率哦! M ...

  3. iTerm2+oh-my-zsh配色

      效果图,很帅气有木有 一.首先安装iTem2 安装好后的截图如下:   安装好后的截图 二.安装oh-my-zsh. sh -c "$(curl -fsSL https://raw.gi ...

  4. Leetcode49. Group Anagrams字母异位词分组

    给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", "tea", "tan&quo ...

  5. bzoj 1045 [HAOI2008] 糖果传递——设变量推式子

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1045 费用流TLE. #include<iostream> #include&l ...

  6. 八.DBN深度置信网络

    BP神经网络是1968年由Rumelhart和Mcclelland为首的科学家提出的概念,是一种按照误差反向传播算法进行训练的多层前馈神经网络,是目前应用比较广泛的一种神经网络结构.BP网络神经网络由 ...

  7. Linux下下载安装jdk1.7和IDEA

    一.安装JDK1.7 准备: 到Oracle官网下载下载jdk1.7,参考博客 https://blog.csdn.net/H12KJGJ/article/details/79240984 官网地址: ...

  8. 【python小随笔】pycharm的永久破解

    PS:这里有人会遇到第一次输入补丁的破解命令后,重启后启动不了软件,这个时候需要卸载(unstall把配置都得删除了),然后重新下载软件,再用这个步骤就OK了~~版本一定要低于最新版本两个以上,最好用 ...

  9. Python高级核心技术97讲 系列教程

    Python高级核心技术97讲 系列教程 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的 ...

  10. FZU 1576【计算几何/费马点】

    Oaiei居住在A城市,并且是这个城市建设的总设计师.最近有个问题一直困恼着他.A城市里有三个大型工厂,每个大型工厂每天都需要消耗大量的石油,现在城市里要建设一个石油中转站,从石油中转站到三个大型工厂 ...