题目

在一个有向图上,从一点A出发,经过所有除A的顶点一次且仅经过一次,最后到达起始点A,所形成的路径为哈密顿环。两个哈密顿环不同,当且仅当路径上的任意一个顶点P的下一个顶点不同。 
    给出一个顶点数目为 <= 12, 边的数目 <= 200(有可能有重边)的有向图的所有可能的哈密顿环的总数。

分析

哈密顿环经过所有的顶点,因此可以从任何一个顶点出发(在程序中就选择起始点为节点0);如果两个顶点之间有重边,那么这些重边对于哈密顿环是等价的,因此在构建图的时候,要去重边。 
    使用深度优先搜索可以求出所有哈密顿环的总数,但是估算一个复杂度: 假设每个顶点都连接其他10个顶点,那么深度优先搜索复杂度约 10^10,不能接受。因此可以考虑使用记忆化搜索结合状态压缩: 
    1、状态用两个维度表示:(1)经过路径(从某个点开始到达节点0)上所覆盖的点;(2)经过的路径的起始点。 
    2、最多一共12个点,可以用一个整数的低12个比特表示经过的路径中这12个点是否被经过。因此使用 dp[status_to_visit][node] 表示从节点node开始,经过的节点的位图为 status_to_visit ,最终到达节点0所有不同的路径的总数。 
    利用记忆化深度优先搜索,求出最终的结果. 
    明确状态很重要,计算清楚边界状态很重要! 
    明确状态很重要,计算清楚边界状态很重要! 
    明确状态很重要,计算清楚边界状态很重要!

实现

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<unordered_map>
#include<list>
#include<string>
#include<string.h>
#include<set>
using namespace std;
int dp[8200][13];
//dp[status][node] 表示从node出发,最终到达点0,遍历的点的状态形成 status 时可以走的路径数目
bool connected[13][13];
struct Edge{
int to;
int next;
};
Edge gEdges[220];
int gEdgeIndex;
int gHead[13];
bool gVisited[13];
void InsertEdge(int u, int v){
if (connected[u][v]) //如果两个节点A和B之间有多条边直接从A连接到B,则只记录一次
return;
connected[u][v] = true;
int e = gEdgeIndex++;
gEdges[e].to = v;
gEdges[e].next = gHead[u];
gHead[u] = e;
} void Init(){
gEdgeIndex = 0;
memset(gEdges, -1, sizeof(gEdges));
memset(gHead, -1, sizeof(gHead));
memset(dp, -1, sizeof(dp));
memset(connected, false, sizeof(connected));
memset(gVisited, false, sizeof(gVisited));
} //用记忆化搜索实现 动态规划
//从node开始,经过的各个节点的位图为 status_to_visit,status_to_visit 中的各个节点经过
//且只经过一次,最终到达节点0. 所有可能的路径总数
int Dfs(int status_to_visit, int node){
if (dp[status_to_visit][node] != -1)
return dp[status_to_visit][node]; //当前节点之前被访问过一次
if ((status_to_visit & (1 << node)) == 0)
return dp[status_to_visit][node] = 0; int result = 0;
for (int e = gHead[node]; e != -1; e = gEdges[e].next){
int v = gEdges[e].to;
int new_status = status_to_visit & (~(1 << node));
result += Dfs(new_status, v);
}
return dp[status_to_visit][node] = result;
} int main(){
int n, m, u, v;
Init();
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++){
scanf("%d %d", &u, &v);
InsertEdge(u - 1, v - 1);
}
//初始状态,从0节点开始,最终到达节点0. status_to_visit = 0 是应为要从0开始到达0,
//在开始的时候,位图为 111111,递归到下一层时为 111110.到最后再到达0时候的status_to_visit 为 000000
dp[0][0] = 1;
int result = Dfs((1 << n) - 1, 0);
printf("%d\n", result);
return 0;
}

hiho_1087_哈密顿环的更多相关文章

  1. NPC

    这里的想说的NPC不是Non-Player-Controled,非玩家控制角色,而是Non-determinisitc Polynomial complete problem,它属于一类很特殊的问题, ...

  2. NOIP算法总结与复习

    NOIP算法总结与复习 (看了看李总的蓝皮书,收获颇多,记下此文,以明志--) (一)数论 1.最大公约数,最小公倍数 2.筛法球素数 3.mod规律公式 4.排列组合数,错排 5.Catalan数 ...

  3. NOIP算法小结(转载)

    (一)数论 1.最大公约数,最小公倍数 2.筛法求素数 3.mod规律公式 4.排列组合数,错排 5.Catalan数 6.康托展开 7.负进制 8.中位数的应用 9.位运算 (二)高精度算法 1.朴 ...

  4. [NOIP2017赛前复习第二期]复赛考试技巧与模版-普及组

    考试技巧 1.拿到考卷首先通看题目,按自己感觉的难度排序(普及一般是1-2-3-4了~还是相信出题人不会坑我们的2333) 2.一般来说,普及组前两道题比较简单(大水题啊233~),但是通常坑很多,例 ...

  5. HDU 3488 Tour (最大权完美匹配)【KM算法】

    <题目链接> 题目大意:给出n个点m条单向边边以及经过每条边的费用,让你求出走过一个哈密顿环(除起点外,每个点只能走一次)的最小费用.题目保证至少存在一个环满足条件. 解题分析: 因为要求 ...

  6. 强化学习论文(Scalable agent alignment via reward modeling: a research direction)

     原文地址: https://arxiv.org/pdf/1811.07871.pdf ======================================================== ...

  7. 条件转化,2-sat BZOJ 1997

    http://www.lydsy.com/JudgeOnline/problem.php?id=1997 1997: [Hnoi2010]Planar Time Limit: 10 Sec  Memo ...

  8. hdoj 3488 Tour 【最小费用最大流】【KM算法】

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submi ...

  9. HihoCoder1087Hamiltonian Cycle(DP状态压缩)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Given a directed graph containing n vertice (numbered from 1 ...

随机推荐

  1. Rigidbody.position/rotation更新测试

    Rigidbody.position/rotation主要提供在下一个物理步之前更新物理位置,一般用于SweepTest这样的接口 那么测试一下会不会修改掉transform.position的值 测 ...

  2. JS 滚动效果

    地址: https://github.com/aamirafridi/jQuery.Marquee <script language="JavaScript" src=&qu ...

  3. JavaScript 中的Object的使用详解笔记(一)

    昨天的学习笔记,今天更新上.第三遍看oop,还是理解的比较到位了.   1.JavaScript的组成:ECMAScript(最新6) + DOM + BOM 2.数组与对象的应用: object的基 ...

  4. 2016年11月18日 星期五 --出埃及记 Exodus 20:9

    2016年11月18日 星期五 --出埃及记 Exodus 20:9 Six days you shall labor and do all your work,六日要劳碌作你一切的工,

  5. 使用StarUML创建类图

    使用StarUML创建类图 http://www.flyne.org/article/379 1.综述(What) StarUML是一种生成类图和其他类型的UML图表的工具.本文是一个使用StarUM ...

  6. VC++界面编程之--阴影窗口的实现详解

    转载:http://blog.csdn.net/rmxming/article/details/11661365 对于我们这些控件狂来说,窗口阴影也是一个必不可少的实现需求.虽说其没多大用,但对于增加 ...

  7. [转]Unity 延迟执行一段代码的较为优雅的方式

    Unity中,延时执行一段代码或者一个方法或者几个方法的情况非常普遍. 一般会用到Invoke和InvokeRepeating方法.顾名思义,第一个是执行一次,第二个是重复执行. 看下定义: void ...

  8. 机器学习——SVM详解(标准形式,对偶形式,Kernel及Soft Margin)

    (写在前面:机器学习入行快2年了,多多少少用过一些算法,但由于敲公式太过浪费时间,所以一直搁置了开一个机器学习系列的博客.但是现在毕竟是电子化的时代,也不可能每时每刻都带着自己的记事本.如果可以掏出手 ...

  9. Intellij IDEA中使用Struts2

    据说struts2中有很多的漏洞, 不过作为学习我也就用了吧, 因为书上面是按着这个讲的呀. 难怪官网上也没有struts2.2.1的版本的下载. 1. 下载struts2.2.1 ga版本 2. 新 ...

  10. [SAP ABAP开发技术总结]局部变量、全局变量

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...