hiho_1087_哈密顿环

题目

在一个有向图上,从一点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;
}
时间: 2024-08-11 09:57:31

hiho_1087_哈密顿环的相关文章

hdoj 3435 A new Graph Game 【无向图判断权值最小哈密顿环】【KM算法】

A new Graph Game Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1934    Accepted Submission(s): 827 Problem Description An undirected graph is a graph in which the nodes are connected by undir

HDU 3488--Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 &amp;&amp; 经典】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2308    Accepted Submission(s): 1156 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

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

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2299    Accepted Submission(s): 1151 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

【听课记录】17-7-11 动态规划 - 朱全民

此文转载时必须通知博主,并把原文链接及原作者放在正文醒目位置. ————————动态规划初步———————— 一.常见动态规划:求最优解.次优解:统计问题. 二.DP模型:线型- 一条直线.两条直线.多条直线(二维矩阵).树型- 明显能够构成一棵树.多叉树转二叉树:孩子兄弟表示法.图型- 以图为模型.基于连通性的状态压缩DP(哈密顿环).集合类型 三.DP概念:阶段.状态.决策.状态转移.最优化原理.无后效性原理. 四.步骤划分阶段—设置状态—状态转移方程—(优化决策) 五.例题分析 —————

NOIP算法总结与复习

NOIP算法总结与复习 (看了看李总的蓝皮书,收获颇多,记下此文,以明志--) (一)数论 1.最大公约数,最小公倍数 2.筛法球素数 3.mod规律公式 4.排列组合数,错排 5.Catalan数 6.康托展开 7.负进制 8.中位数的应用 9.位运算 (二)高精度算法 1.朴素加法减法 2.亿进制加法减法 3.乘法 4.除法 5.亿进制读入处理 6.综合运用 (三)排序算法 1.冒泡 2.快排 3.堆排 4.归并 (四)DP 1.概念 2.解题步骤 3.背包类dp 4.线性dp 5.区间动态

hdoj 3488 Tour 【经典最小费用最大流】

题目:hdoj 3488 Tour 题意:给出n个点m条边,然后让你求每个点只能在一个环中(哈密顿环),且所有点只走一次的最小费用. 分析:直接画图的话可能没有思路,但是把它化成一个二分图的话肯定瞬间思路来了,每个点只走一次,很好建图 建图方案: 每个点拆成两个i 和 ii 然后s连接所有 i ,容量1 ,费用0 ii 连接所有 t ,容量 1 ,费用0 所有右边的点 xi 连接 yii ,费用为权值,容量0 AC代码: #include <cstdlib> #include <ccty

NPC

这里的想说的NPC不是Non-Player-Controled,非玩家控制角色,而是Non-determinisitc Polynomial complete problem,它属于一类很特殊的问题,迄今为止,没有人能够找出求解NPC问题的多项式时间的算法,同时也没有人能够证明对于这类问题不存在多项式时间算法: 最短(Bellman -Ford)与最长简单路径,欧拉游程(Fleury)和哈密顿回路,2-CNF可满足性和3-CNF可满足性,这些问题看起来差别很小,但是成对的问题中前者存在多项式时间

算法课笔记系列(八)——NP问题及其计算复杂性

本周的内容是NP问题,NP的全称是Non-deterministic Polynomial,即多项式复杂程度的非确定性问题.百度上对NP的解释是,P/NP问题是在理论信息学中计算复杂度理论里至今没有解决的问题.通俗的说,是将不可知的问题转化为已知的问题,进而计算器复杂度. 首先介绍多项式时间的约减,即Polynomial-Time Reductions,通过解决另一个不同问题的假设的子程序,使用不包含子程序在内的多项式时间来解决一个问题的方法.主观上,一个多项式时间约减证明了第一个问题不比第二个

算法分析与设计入门-搜索策略

来源于:网易云课堂-哈工大-王宏志老师 1.暴力美学 问题1.布尔表达式的可满足性问题(NP完全问题)  解1.时间复杂度是2^n. 问题2.8迷问题 解2.转换为树搜索问题,对可能的移动结果生成解空间 问题3.哈密顿环问题(NP完全问题) 解3.从原点出发,对可能访问到的点生成解空间,并且从每个可以访问到的点出发,若一个点的出发的所有边已经被访问过,那么就结束当前的点.如果所有的点的都不能走,就没有哈密顿环. 原文地址:https://www.cnblogs.com/BlueBlueSea/p