题解

我们从最简单的思路开始考虑,首先看到题目发现\(n\)非常小,于是很容易想到状态压缩。

我们考虑比较直觉的状态,f[i][j][k]表示以i为起点,当前在j,之前去过的点状态为k的简单环的方案数。

仔细思考以后,我们发现这个状态有问题,问题在于,每一个环再环内的每个点都被计算了一次。

那么怎么避免这种状态呢?我们考虑让每个环仅由其中编号最小的点贡献。

这样操作了以后,每个环仍然被计算了两遍(顺时针一次,逆时针一次),但是关系不大,最后统计答案的时候除2即可。

考虑到起点已经是环中最小的点了,于是我们无需再状态里额外记录它。

于是将状态变换成f[i][j]表示当前在i,之前去过的点状态为j的简单环的方案数。

那么状态之间如何转移呢?直接DP有些困难,于是我们使用记忆化搜索。

在记忆化搜索的时候要记录一个值表示当前去过几个点,因为显然数量在2即以下的点构不成简单环,但会被记搜记录答案,特判即可。

代码

#include <cstdio>

namespace fast_IO{
const int IN_LEN = 10000000, OUT_LEN = 10000000;
char ibuf[IN_LEN], obuf[OUT_LEN], *ih = ibuf + IN_LEN, *oh = obuf, *lastin = ibuf + IN_LEN, *lastout = obuf + OUT_LEN - 1;
inline char getchar_(){return (ih == lastin) && (lastin = (ih = ibuf) + fread(ibuf, 1, IN_LEN, stdin), ih == lastin) ? EOF : *ih++;}
inline void putchar_(const char x){if(oh == lastout) fwrite(obuf, 1, oh - obuf, stdout), oh = obuf; *oh ++= x;}
inline void flush(){fwrite(obuf, 1, oh - obuf, stdout);}
int read(){
int x = 0; int zf = 1; char ch = ' ';
while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar_();
if (ch == '-') zf = -1, ch = getchar_();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar_(); return x * zf;
}
void write(long long x){
if (x < 0) putchar_('-'), x = -x;
if (x > 9) write(x / 10);
putchar_(x % 10 + '0');
}
} using namespace fast_IO; struct Edge{
int to, next;
} edges[1005]; int head[20], edge_num = 0; inline void addEdge(int from, int to){
edges[++edge_num] = (Edge){to, head[from]};
head[from] = edge_num;
} long long f[20][1048577];
int vis[20]; long long DFS(int frt, int u, int sta, int cnt){
vis[u] = 1;
if (f[u][sta])
return f[u][sta];
for (int c_e = head[u]; c_e; c_e = edges[c_e].next){
int v = edges[c_e].to;
if ((1 << (v - 1)) & sta){
if (cnt > 2 && v == frt)
++f[u][sta];
}
else
if (v > frt)
f[u][sta] += DFS(frt, v, sta | (1 << (v - 1)), cnt + 1);
}
return f[u][sta];
} int main(){
int n = read(), m = read();
for (int i = 0; i < m; ++i){
int u = read(), v = read();
addEdge(u, v), addEdge(v, u);
}
long long ans = 0;
for (int i = 1; i <= n; ++i)
ans += DFS(i, i, (1 << (i - 1)), 1);
write(ans / 2); flush();
return 0;
}

[CF11D]A Simple Task 题解的更多相关文章

  1. 【题解】 CF11D A Simple Task

    [题解] CF11D A Simple Task 传送门 \(n \le 20\) 考虑状态压缩\(dp\). 考虑状态,\(dp(i,j,O)\)表示从\(i\)到\(j\)经过点集\(O\)的路径 ...

  2. CF11D A Simple Task 状压DP

    传送门 \(N \leq 19\)-- 不难想到一个状压:设\(f_{i,j,k}\)表示开头为\(i\).结尾为\(j\).经过的点数二进制下为\(k\)的简单路总数,贡献答案就看\(i,j\)之间 ...

  3. CF11D A Simple Task(状压DP)

    \(solution:\) 思路大家应该都懂: 状压DP:\(f[i][j]\),其中 \(i\) 这一维是需要状压的,用来记录19个节点每一个是否已经走过(走过为 \(1\) ,没走为 \(0\) ...

  4. CF 11D A Simple Task 题解

    题面 这道题的数据范围一看就是dfs或状压啦~ 本文以状压的方式来讲解 f[i][j]表示目前的节点是i,已经经历过的节点的状态为j的简单环的个数: 具体的转移方程和细节请看代码: PS:(i& ...

  5. Codeforces Round #312 (Div. 2) E. A Simple Task 线段树

    E. A Simple Task 题目连接: http://www.codeforces.com/contest/558/problem/E Description This task is very ...

  6. Codeforces Round #312 (Div. 2) E. A Simple Task 线段树+计数排序

    题目链接: http://codeforces.com/problemset/problem/558/E E. A Simple Task time limit per test5 secondsme ...

  7. 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task

    E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...

  8. HDU-1339 A Simple Task

    http://acm.hdu.edu.cn/showproblem.php?pid=1339 正常做法超时,要有点小技巧存在. A Simple Task Time Limit: 2000/1000 ...

  9. A Simple Task

    A Simple Task Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

随机推荐

  1. java读取文件完整版

    public static void readFileByBytes(String fileName) { File file = new File(fileName); InputStream in ...

  2. mysql 导出 导入sql 文件

    C:\Users\Eric>mysqldump -uroot -p      demo->数据库名 >  C:\Users\Eric\demo.sql    导出目录地址 导入 sq ...

  3. 786B - Legacy(线段树 + 最短路)线段树优化建图

    题意: 就是给定一张n nn个点的图,求源点s ss到每个点的单源最短路.这张图共有q组边,连边方式有3种: a→b ,边权为w的单向边:a→[l,r] ,即a到连续区间[l,r]中的每一个点都有一条 ...

  4. 在Ueditor的内容区添加一个下拉选框改变事件

    <script>html='';html=html+` <select name="" onchange='this.appendChild(document.g ...

  5. NTFS,FAT32和exFAT文件系统的区别

    NTFS,FAT32和exFAT文件系统的区别 本文所有资料来源于网络,仅做个人学习使用,如有侵权,请联系删除 1.什么是文件系统 文件系统是系统对文件的存放排列方式,不同格式的文件系统关系到数据是如 ...

  6. java io 文件读写操作

    写: import java.io.*; String filePath= "F:\\test.txt"; FileWriter fwriter = null; fwriter = ...

  7. TS学习

    随着vue3.0的即将到来,是时候学习一下TS了 简介:TypeScript是一种由微软开发的自由和开源的编程语言.它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类 ...

  8. TCP的三次握手与四次挥手理解及面试题

    TCP的三次握手与四次挥手理解及面试题(很全面) 转载自:https://blog.csdn.net/qq_38950316/article/details/81087809 本文经过借鉴书籍资料.他 ...

  9. join 与 countdownlatch 的区别 扩展 栅栏 CyclicBarrier

    我们先看一个 小例子 , 使用 join 与CountDownSlatch 都可以完成 当1,2线程 完全结束后 3 线程 start 对比我们就能够知道 CountDownSlatch 比 JOIN ...

  10. ARM调试器只能偶尔连接成功问题

    这里分析一个ARM板子JTAG调试器经常连接失败,只能偶尔连上目标板问题. 背景 这是原先另一个部门的板子,在部门合并之后,最近要对这个板子的代码体系进行转移,在过问开发进度时,工程师反映这个板子调试 ...