目录

一,哈密顿回路、哈密顿链路

二,Dirac定理

三,算法

力扣 996. 正方形数组的数目

力扣 980. 不同路径 III

四,竞赛图

五,相关puzzle

1,数字满格

2,马的哈密顿回路、链路


一,哈密顿回路、哈密顿链路

图的哈密顿回路是指包含图的所有节点的回路。

图的哈密顿链路是指包含图的所有节点的链路。

二,Dirac定理

如果G是一个n(n≥3)个点的无向简单图,所有节点的度数都 ≥ n/2.0,则G中存在哈密顿回路。

证明过程:

(1)G是连通图

(2)设最长路径是L,用抽屉原理可以证明L是个环

(3)如果有节点不在环中,根据连通性可以加入一个点把环变成一条更长的路径。所以所有节点都在这个环中。

三,求解哈密顿链路

哈密顿问题其实和TSP问题差不多,是NP问题,没有特别好的算法。

回溯法:

class Hamilton
{
public:stack<int> hami;//哈密顿链路Hamilton(int n, map<int, vector<int>>& m, int type)//type=0是无向图 1是有向图{this->n = n;this->m = m;this->type = type;for (int i = 0; i < n; i++)dfs(i);}
private:bool dfs(int k){s.push(k);if (s.size() == n) {hami = s;return true;}for (auto nk : m[k]) {if (visit[k])continue;visit[k] = 1;if (dfs(nk))return true;visit[k] = 0;}s.pop();return false;}int n;int type;map<int, vector<int>> m;//邻接表map<int, int>visit;stack<int>s;
};

力扣 996. 正方形数组的数目

给定一个非负整数数组 A,如果该数组每对相邻元素之和是一个完全平方数,则称这一数组为正方形数组。

返回 A 的正方形排列的数目。两个排列 A1 和 A2 不同的充要条件是存在某个索引 i,使得 A1[i] != A2[i]。

示例 1:

输入:[1,17,8]
输出:2
解释:
[1,8,17] 和 [17,8,1] 都是有效的排列。

示例 2:

输入:[2,2,2]
输出:1

提示:

  1. 1 <= A.length <= 12
  2. 0 <= A[i] <= 1e9
vector<int> gnums;
class Hamilton
{
public:map<long long, int>ans;Hamilton(int n, map<int, vector<int>>& m, int type)//type=0是无向图 1是有向图{this->n = n;this->m = m;this->type = type;for (int i = 0; i < n; i++)dfs(i,1);}
private:bool dfs(int k,int deep){if (visit[k])return false;long long h2 = h;hash(k);if (hashVisit[h])goto RET;hashVisit[h] = 1;if (deep == n) {ans[h] = 1;h = h2;return true;}visit[k] = 1;for (auto nk : m[k]) {dfs(nk,deep+1);}RET:visit[k] = 0;h = h2;return false;}void hash(int k){h = ((h * (gnums[k]+123) + 666) * 789)%1000000007;}int n;int type;map<int, vector<int>> m;//邻接表map<int, int>visit;map<long long, int>hashVisit;long long h = 1234567;
};class Solution {
public:int numSquarefulPerms(vector<int>& nums) {int n = nums.size();map<int, vector<int>>m;for (int i = 0; i < n; i++)for (int j = i + 1; j < n; j++) {if (isSquare(nums[i] + nums[j]))m[i].push_back(j), m[j].push_back(i);}gnums = nums;return Hamilton(n, m, 0).ans.size();}bool isSquare(int n) {int x = sqrt(n);return x * x == n;}
};

力扣 980. 不同路径 III

在二维网格 grid 上,有 4 种类型的方格:

  • 1 表示起始方格。且只有一个起始方格。
  • 2 表示结束方格,且只有一个结束方格。
  • 0 表示我们可以走过的空方格。
  • -1 表示我们无法跨越的障碍。

返回在四个方向(上、下、左、右)上行走时,从起始方格到结束方格的不同路径的数目

每一个无障碍方格都要通过一次,但是一条路径中不能重复通过同一个方格

示例 1:

输入:[[1,0,0,0],[0,0,0,0],[0,0,2,-1]]
输出:2
解释:我们有以下两条路径:
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2)
2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)

示例 2:

输入:[[1,0,0,0],[0,0,0,0],[0,0,0,2]]
输出:4
解释:我们有以下四条路径:
1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3)
2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3)
3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3)
4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)

示例 3:

输入:[[0,1],[2,0]]
输出:0
解释:
没有一条路能完全穿过每一个空的方格一次。
请注意,起始和结束方格可以位于网格中的任意位置。

提示:

  • 1 <= grid.length * grid[0].length <= 20
class Hamilton
{
public:map<long long, int>ans;Hamilton(int n, map<int, vector<int>>& m, int type,int start,int e)//type=0是无向图 1是有向图{this->n = n;this->m = m;this->type = type;this->e = e;dfs(start,1);}
private:bool dfs(int k,int deep){if (visit[k])return false;long long h2 = h;hash(k);if (hashVisit[h])goto RET;hashVisit[h] = 1;if (deep == n) {ans[h] = 1;h = h2;return true;}visit[k] = 1;for (auto nk : m[k]) {if (deep < n - 1 && nk == e)continue;dfs(nk,deep+1);}RET:visit[k] = 0;h = h2;return false;}void hash(int k){h = ((h * (k+123) + 666) * 789)%1000000007;}int n;int type;map<int, vector<int>> m;//邻接表map<int, int>visit;map<long long, int>hashVisit;long long h = 1234567;int e;
};class Solution {
public:int uniquePathsIII(vector<vector<int>>& grid) {row=grid.size(),col = grid[0].size();int n = row*col;map<int, vector<int>>m;int s, e;for (int i = 0; i < row; i++)for (int j = 0; j < col; j++) {if (grid[i][j] == -1) {n--;continue;}if (grid[i][j] == 1)s = id(i, j);if (grid[i][j] == 2)e = id(i, j);vector<int> v = getNeighbor4(id(i, j));for (int k : v)if(grid[k/col][k%col]!=-1)m[k].push_back(id(i, j));}return Hamilton(n, m, 0,s,e).ans.size();}int id(int x, int y){return x * col + y;}vector<int> getNeighbor4(int k){vector<int>ans;if (k >= col)ans.push_back(k - col);if (k < (row - 1) * col)ans.push_back(k + col);if (k % col)ans.push_back(k - 1);if (k % col < col - 1)ans.push_back(k + 1);return ans;}int row,col;
};

四,竞赛图

竞赛图必有哈密顿链路。

竞赛图中不存在环当且仅当所有顶点的出度从小到大排列依次为0, 1, 2, … , n-1 。

翻译成赛事语言就是,单循环赛结果没有环,当且仅当所有人的实力是线性排序的,没有任何一次比赛发生逆袭现象。

五,相关puzzle

1,数字满格

4399在线play

每个格子有8个邻居(部分格子可能只有3-7个邻居),按照这种关系把100个格子转化成无向图,寻找此图的曼哈顿链。

到90是比较容易的,到100就比较难了。

2,马的哈密顿回路、链路

定理:

如果n是偶数(n>4)那么n*n的棋盘有一个哈密顿回路。

如果n是奇数(n>3)那么n*n的棋盘有一个哈密顿链路。

像这样的图还可以构造一些,不过基本上都差不多。

总结起来就是,最中间的格子是比较特殊的,上图中标号1-8的这8个格子构成1个回路,

其余的16个格子也构成1个回路,相当于5*5的棋盘其实就是3个回路组合而成,只要适当地选择断点,即可把3个回路连接成一条链。

如果选取的起点不同,得到的哈密顿链还是略有区别的。

比如:112象棋(12)

关于上面的2个定理,书上的意思是用数学归纳法来证明,从n=k变成n=k+4相当于在原来的基础上,套上了一个宽度为2的边框。这个边框是若干个哈密顿回路组成的,只要在适当的地方断开,就可以和里面的k*k连接起来。

下面讨论,7*7的棋盘去掉中间的3*3如何形成哈密顿回路。

首先,角落的点只有2个邻居,那么在回路里面,这2个点也一定都是他的邻居。

其他的,以此类推,可以得到下图:

对于那些已经连了2条线的点,自然是没有任何悬念了,所以接下来只需要考虑那些恰好连了1条线的点该如何连接起来。将上图化简如下:

黑色的线表示一定相连,红色的线表示可能相连。

这样,可以得到这16个点的哈密顿回路:

与此对应,可以得到原图:

这是由2个哈密顿回路构成的。

这样,整个通过把大的回路断开一个地方,可以得到下图:

在把紫色的哈密顿回路和这个长为41的哈密顿链连接起来,即可得到7*7的哈密顿链

哈密顿回路、链路、竞赛图相关推荐

  1. P4233-射命丸文的笔记【NTT,多项式求逆】

    正题 题目链接:https://www.luogu.com.cn/problem/P4233 题目大意 随机选择一条有哈密顿回路的nnn个点的竞赛图,求选出图的哈密顿回路的期望个数. 对于每个n∈[1 ...

  2. 【GDOI2018】所有题目和解题报告

    使用说明:题意和数据范围都只是回忆内容,仅供参考.题解陆续补上. Day 1 第一题 题意:给定n个数字,要求划分成k的连续段使得每个连续段内的数字之和相同,求最大的k.n,Σai<=10^6. ...

  3. 【LuoguP4233】射命丸文的笔记-多项式求逆

    测试地址:射命丸文的笔记 做法:本题需要用到多项式求逆. 首先,要求存在哈密顿回路的竞赛图的哈密顿回路期望数量,就是用哈密顿回路的总数除以存在哈密顿回路的竞赛图数量. 要考虑所有竞赛图的哈密顿回路数量 ...

  4. luogu P4233 射命丸文的笔记

    题意: 给出nnn,求对于任意的1≤i≤n" role="presentation" style="position: relative;">1 ...

  5. bzoj4727 [POI2017]Turysta(竞赛图构造哈密顿回路)

    bzoj4727 [POI2017]Turysta 原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=4727 题意: 给出一个n个点的有向图, ...

  6. 哈密顿回路 竞赛图 构造哈密顿回路(待更新)

    哈密顿回路 1.哈密顿回路 图G的一个回路,该回路除了经过初始结点两次以外,恰好经过每个结点一次,则称此回路为哈密顿回路.哈密顿回路中每个结点都为偶结点且入度和出度均为1 2.哈密顿路径 一条路径上每 ...

  7. UCF Locals 2015(A~I(竞赛图+哈密顿回路))

    cf题目链接 计蒜客题目链接 献上官方题解 注意cf和计蒜客的输出格式是不一样的,我在cf能A的,就没去计蒜客验证了 A-Find the Twins 水题 注意输出格式就行了. #include&l ...

  8. 【算法笔记】竞赛图(有向完全图)(相关题型总结)

    整理的算法模板合集: ACM模板 目录 竞赛图(有向完全图) 一.兰道定理 例题HDU 5873 Football Games 二.求竞赛图的任意三元环 三.求竞赛图的哈密顿回路数量的期望 竞赛图(有 ...

  9. BZOJ.4727.[POI2017]Turysta(哈密顿路径/回路 竞赛图)

    题目链接 \(Description\) 给出一个n个点的有向图,任意两个点之间有且仅一条有向边.对于每个点v,求出从v出发的一条经过点数最多,且没有重复经过同一个点一次以上的简单路径. n<= ...

最新文章

  1. 让线上学习不打折扣,作业帮如何用技术促进课堂高频互动场?
  2. 在电影里看到的一个小故事
  3. 01【在线日志分析】之Flume-1.7.0源码编译导入eclipse
  4. linux find 拷贝,通过find命令寻找文件并拷贝到一个指定目录方法详解
  5. python 装饰器应用
  6. python restful风格_总结python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE方法
  7. xampp 中 mysql的相关配置
  8. 【文文殿下】APIO2019游记
  9. MySQL数据库优化概述
  10. python使用t检验和F检验验证模型好坏
  11. 【组合数学 】 推广牛顿二项式 ( 牛顿二项式推广 | 推导流程 | 题目解析 )
  12. PayPal支付集成到自己Web网站
  13. 百度APP“看听模式”:“AI主播”借道信息流全面落地?
  14. 【polar码】polar编译码以及SC译码算法的matlab仿真验证,对比不同编码码率的误码率性能
  15. HihoCoder——Trie树
  16. 一些好用的APP分享
  17. JS基础_Unicode编码表
  18. BLE学习.osal学习1.osal的任务与事件
  19. vb.NET入门总结
  20. 使用C# winform 制作一个按钮可自适应屏幕大小的 简易加减乘除计算器

热门文章

  1. 如何优化页面加载速度
  2. 安装dd-wrt_如何在家庭路由器(DD-WRT)上安装其他软件
  3. 技术与艺术的结合,HMS Core让手机主题趣味丛生
  4. 如果高冷地看待市面上培训班?
  5. 如何使用APPLE watch解锁你的MACBOOK
  6. DevOps —— 持续交付
  7. 使用cordova的加强webview
  8. Python+Selenium基础入门及实践
  9. 【100%通过率】华为OD机试真题 C++ 实现【整理扑克牌】【2022.11 Q4 新题】
  10. 树莓派kali ettercap断网攻击