[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 ...
随机推荐
- Linux最佳的云存储服务分析
什么样的云服务才适合作为 Linux 下的存储服务?兄弟连www.itxdl.cn来帮大家分析一下! 大量的免费空间.毕竟,个人用户无法支付每月的巨额款项. 原生的 Linux 客户端.以便你能够方便 ...
- bootbox的使用
/* * className为green的方法 */ function alertMsgG(msg,title,fn){ bootbox.alert({ buttons: { ok: { label: ...
- 排序算法Java实现(直接插入排序)
算法描述:对于给定的一个数组,初始时假设第一个记录自成一个有序序列,其余记录为无序序列.接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直至最后一个记录插入到有序序列 ...
- Gitlab - Pull Request
1.概述 今天查看Gmail,有网友私密我Gitlab的Pull Request工作流程,一直以为我写过这片博客,查看<Git和Gitlab协同工作>却发现遗漏了Pull Request这 ...
- 去除Vue在WebStorm中报命名空间的错误
Preferences -> Editor -> Inspections找到XML,把 Unbound XML namespace prefix的勾去掉
- 【Flask】 WTForm表单编程
WTForm表单编程 在网页中,为了和用户进行信息交互总是不得不出现一些表单.flask设计了WTForm表单库来使flask可以更加简便地管理操作表单数据.WTForm中最重要的几个概念如下: Fo ...
- 大数据 --> MapReduce原理与设计思想
MapReduce原理与设计思想 简单解释 MapReduce 算法 一个有趣的例子:你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃? MapReduce方法则是: 给在座 ...
- php正则相关知识点
关于正则,其实简单就是搜索和匹配.php,java,python等都是支持正则的,php正则兼容perl.好多同学觉得正则比较难,比较抽象,其实正则是非常简单的,主要是一个熟悉和反复练习的结果,还有一 ...
- “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift
使用cocopod导入第三方swift包后,编译报以下错误: The "Swift Language Version" (SWIFT_VERSION) build setting ...
- C语言第九次作业
一.PTA实验作业 题目1:统计大于等于平均分人数 1. 本题PTA提交列表 2.设计思路 float i为循环变量,sum=0,count=0来表示所求人数 float *p=s来储存首地址 for ...