[CodeForces 11D] A Simple Task - 状态压缩入门
状态压缩/Bitmask
在动态规划问题中,我们会遇到需要记录一个节点是否被占用/是否到达过的情况。而对于一个节点数有多个甚至十几个的问题,开一个巨型的[0/1]数组显然不现实。于是就引入了状态压缩,用一个整数的不同二进制位来表示该节点的状态。
Description
- Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no repeated vertices or edges.
Input&Output
Input
- The first line of input contains two integers n and m (1 ≤ n ≤ 19, 0 ≤ m) – respectively the number of vertices and edges of the graph. Each of the subsequent m lines contains two integers a and b, (1 ≤ a, b ≤ n, a ≠ b) indicating that vertices a and b are connected by an undirected edge. There is no more than one edge connecting any pair of vertices.
Output
- Output the number of cycles in the given graph.
Sample
Input
4 6
1 2
1 3
1 4
2 3
2 4
3 4
Output
7
Solution
- 大意是求简单无向图的环数,暴搜遍历必然会TLE,重复环的处理也十分复杂。
- 考虑状态压缩,用二进制位来表示当前状态是否经过了特定的点。为了减轻重复环的处理难度,我们约定只计算起点序小于当前节点的状态(在代码中会有解释)。若节点i与当前节点y之间有边,状态的转移有以下几种条件:
- 若当前状态的起点序大于当前节点 (k&-k>(1<<y)) ,不转移。
- 若当前状态经过了当前节点 (k&(1<<y)) ,判断起点是否就是当前节点,若是,意味着我们找到了环,更新答案。
- 若当前状态没有经过当前节点,则更新经过当前节点的状态 f[k|(1<<y)][y] ,由 f[k][i] 贡献。
- 遍历以每个节点为起点的所有状态,我们可以得到一个ans。但需要注意的是,这种计算方式会将两点间连一条边的路径(为什么?)和一个环的双向都计算在内,输出时需要将答案减去边数再除以2.
细节与边界处理 - 由于二进制位需要从第0位开始,我们不妨在建图时同一将点的编号减1,方便计算。节点的遍历也要从0到n-1。
- 初始状态下,以节点i为起点,只经过i的状态,f值为1。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 20 #define maxe 400 using namespace std; typedef long long ll; struct edge{ int to,nxt; }e[maxe]; int n,m,x,y,edgenum,lnk[maxn]; ll ans,f[1<<maxn][maxn]; void add(int bgn,int end)//事实上,节点比较少,邻接矩阵也可以存下 { edgenum++; e[edgenum].to=end; e[edgenum].nxt=lnk[bgn]; lnk[bgn]=edgenum; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); add(x-1,y-1); add(y-1,x-1); } for(int i=0;i<n;++i)f[1<<i][i]=1; for(int k=0;k<(1<<n);++k){ for(int i=0;i<n;++i){ if(!f[k][i])continue; for(int p=lnk[i];p;p=e[p].nxt){ int y=e[p].to; if((k&-k)>(1<<y))continue;//判断起点序 if(k&(1<<y)){ if((k&-k)==(1<<y))//判断环 ans+=f[k][i]; } else f[k|(1<<y)][y]+=f[k][i]; } } } ans=(ans-m)/2; printf("%I64d",ans); return 0; }
[CodeForces 11D] A Simple Task - 状态压缩入门的更多相关文章
- CodeForces - 11D A Simple Task
Discription Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycl ...
- Codeforces 11D A Simple Task 统计简单无向图中环的个数(非原创)
太难了,学不会.看了两天都会背了,但是感觉题目稍微变下就不会了.dp还是摸不到路子. 附ac代码: 1 #include<iostream> 2 #include<cstdio> ...
- Codeforces C. A Simple Task(状态压缩dp)
题目描述: A Simple Task time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...
- Codeforces 558E A Simple Task (计数排序&&线段树优化)
题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...
- Codeforces 558E A Simple Task(权值线段树)
题目链接 A Simple Task 题意 给出一个小写字母序列和若干操作.每个操作为对给定区间进行升序排序或降序排序. 考虑权值线段树. 建立26棵权值线段树.每次操作的时候先把26棵线段树上的 ...
- Codeforces 580D Kefa and Dishes(状态压缩DP)
题目链接:http://codeforces.com/problemset/problem/580/D 题目大意:有n盘菜每个菜都有一个满意度,k个规则,每个规则由x y c组成,表示如果再y之前吃x ...
- CodeForces 588E A Simple Task(线段树)
This task is very simple. Given a string S of length n and q queries each query is on the format i j ...
- Codeforces J. A Simple Task(多棵线段树)
题目描述: Description This task is very simple. Given a string S of length n and q queries each query is ...
随机推荐
- python趣味 ——奇葩的全局形参
在c++,c#,js等语言中: 函数定义(参数) 函数体:参数修改 这里的参数修改都是仅限于这个函数体内的 python不知道是不是bug,我们这样写: def test(a=[]): a.appen ...
- 原生js+canvas实现滑动拼图验证码
上图为网易云盾的滑动拼图验证码,其应该有一个专门的图片库,裁剪的位置是固定的.我的想法是,随机生成图片,随机生成位置,再用canvas裁剪出滑块和背景图.下面介绍具体步骤. 首先随便找一张图片渲染到c ...
- spring jpa 自定义查询数据库的某个字段
spring jpa 提供的查询很强大, 就看你会不会用了. 先上代码, 后面在解释吧 1. 想查单个表的某个字段 在repository中 @Query(value = "select i ...
- JS基础三
1.delete删除对对象的属性和方法的定义.强制解除对它的引用,将其设置为 undefined delete 运算符不能删除开发者未定义的属性和方法. 2.void 运算符对任何值返回 undefi ...
- Object.defineProperty实现数据绑定
1.Object.defineProperty方法 Object.defineProperty(obj, prop, descriptor); (1)参数: obj:目标对象 prop:需要定义的属 ...
- Sqlite库的基本操作
Sqlite 基本操作 打开数据库 sqlite3* SQ_DB; char *zErrMsg = 0; int nRes = sqlite3_open("test.db", &a ...
- Redis的安装和部署
基本知识 1.Redis的数据类型: 字符串.列表(lists).集合(sets).有序集合(sorts sets).哈希表(hashs) 2.Redis和memcache相比的独特之处: (1)re ...
- js实现单双行文本溢出添加省略号
# 单双行文本溢出省略 ``` // 2. 当内容过多的时候,单行省略号: overflow: hidden; text-overflow:ellipsis; white-space: nowrap; ...
- 在Anacoda中管理多个版本Python
win10. 在cmd窗口中输入 conda info --envs 或者 conda env list 查看已经安装的环境,当前活动的环境前会加*号. 在cmd窗口(终端窗口)或anaconda p ...
- UI线程异常处理方法
当应用程序启动,创建了一个叫“main”的线程,用于管理UI相关,又叫UI线程.其他线程叫工作线程(Work Thread). Single Thread Model 一个组件的创建并不会新建一个线程 ...