[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 ...
随机推荐
- cesium 显示北京时间
cesium用的JulianDate:代表天文朱利安时间,用的是世界协调时,比北京时间晚8个小时,所以在源代码中给默认的时间格式加上8小时. 应该会有更好的办法,希望有大神可以告诉我!!!!!!!!! ...
- 微信小程序学习笔记(阶段一)
一阶段学习过程: (一)看官方文档的简易教程:https://mp.weixin.qq.com/debug/wxadoc/dev/ (二)看小码哥视频:https://chuanke.baidu.co ...
- Java 面试宝典-2017
http://www.cnblogs.com/nelson-hu/p/7190163.html Java面试宝典-2017 Java面试宝典2017版 一. Java基础部分........... ...
- MYSQL数据库学习八 触发器的操作
8.1 触发器 在表发生更改时,自动进行一些处理.例如,学生表中每增加一条关于学生记录时,学生的总数就必须同时改变,同时需要检查电话号码格式是否正确,地址缩写是否正确. 以下语句会激活触发器: DEL ...
- System V IPC 之共享内存
IPC 是进程间通信(Interprocess Communication)的缩写,通常指允许用户态进程执行系列操作的一组机制: 通过信号量与其他进程进行同步 向其他进程发送消息或者从其他进程接收消息 ...
- 基于Multiple treatment的营销评估算法
营销是发现或挖掘准消费者和众多商家需求,通过对自身商品和服务的优化和定制,进而推广.传播和销售产品,实现最大化利益的过程.例如,银行可通过免息卡或降价对处在分期意愿边缘的用户进行营销,促使其分期进而提 ...
- 简单谈谈DNS的工作原理及实践
DNS协议简介 dns(Domain Name System)是一个全球化的分布式数据库系统,用于存储域名和互联网IP地址的映射关系.dns协议是计算机协议栈应用层中,应用最广泛的协议之一.用户每一次 ...
- C++多线程学习之(一)——并发与多线程
1 并发 计算机领域的并发指的是在单个系统里同时执行多个独立的任务,而非顺序地进行一些活动. 1.1 并发的途径 多进程并发:将应用程序分为多个独立的进程,它们在同一时刻运行,就像同时进行网页浏览和文 ...
- JavaScript(第七天)【对象和数组】
什么是对象,其实就是一种类型,即引用类型.而对象的值就是引用类型的实例.在ECMAScript中引用类型是一种数据结构,用于将数据和功能组织在一起.它也常被称做为类,但ECMAScript中却没有这种 ...
- %f使用时的注意事项
1不是所有定义都用int,使用浮点函数需要把int改成float才能正常工作 2保留一位小数时要打入%0.1f,保留两位小数时要打入%0.2f,而不是%0.01f