定理1:在一个具有n个顶点的无向连通图G中,如果任意两个顶点的度数之和大于n,则G具有Hamilton回路。此条件为充分条件

定理2:设图G = <V,E>,是Hamilton图,则对于v的任意一个非空子集S,若以|S|表示S中元素数目,G-S表示G中删除了S中的点以及与这些点关联的边后得到的子图,则满足G-S的连通分支数W(G-S)<=|S|。此条件为必要条件。

构造Hamilton回路的算法过程,分成以下几个步骤:

1. 任意找两个相邻的节点 S 和 T,在它们基础上扩展出一条尽量长的没有重复节点的路径。也就是说,如果 S 与节点 v 相邻,而且 v 不在路径 S → T 上,则可以把该路径变成 v → S → T,然后 v 成为新的 S。从 S 和 T 分别向两头扩展,直到无法扩为止,即所有与 S 或 T 相邻的节点都在路径 S → T 上。
2. 若 S 与 T 相邻,则路径 S → T 形成了一个回路。
3. 若 S 与 T 不相邻,可以构造出一个回路。设路径 S → T 上有 k + 2 个节点,依次为 S、 v1、 v2…… vk 和 T。可以证明存在节点 vi, i ∈ [1, k),满足 vi 与 T 相邻,且 vi+1 与 S 相邻。证明方法也是根据鸽巢原理,既然与 S 和 T 相邻的点都在该路径上,它们分布的范围只有 v1 ∼ vk 这 k 个点, k ≤ N - 2,而 d(S) + d(T) ≥ N,那么可以想像,肯定存在一个与 S 相邻的点 vi 和一个与 T 相邻的点 vj, 满足 j < i。那么上面的命题也就显然成立了。

找到了满足条件的节点 vi 以后,就可以把原路径变成 S → vi+1 → T → vi → S,即形成了一个回路。
4. 现在我们有了一个没有重复节点的回路。如果它的长度为 N,则汉密尔顿回路就找到了。

如果回路的长度小于 N,由于整个图是连通的,所以在该回路上,一定存在一点与回路以外的点相邻。那么从该点处把回路断开,就变回了一条路径。再按照步骤 1 的方法尽量扩展路径,则一定有新的节点被加进来。接着回到步骤 2。

模板题:POJ 2438 or HDU 4337 Childrens Dining

问题是求小朋友围着桌子的座次就是求原图中的一个环,但是要求这个环不能包含所给出的每条边,所以没给出的边却是可以使用的,也就是说本题实际上是在原图的反图上求一个环,即在每两个可以坐在相邻位置的小朋友连一条边,否则不连。使得该环包含所有顶点,即Hamilton回路。

由于有2n个小朋友,且每个小朋友的敌人最多n-1个,所以,每个小朋友可以一起与座的小朋友最少有n+1个,即度数>=n+1,所以任意两个小朋友度数之和d(u)+d(v)>=2n+2 > 2n,所以Hamilton回路存在。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 407 int vis[N],mp[N][N],ans[N];
int n,m; void init()
{
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
if(i == j)
mp[i][j] = ;
else
mp[i][j] = ;
}
}
memset(ans,,sizeof(ans));
}
void reverse(int ans[N],int s,int t) //将ans数组中s到t的部分倒置
{
int tmp;
while(s < t)
{
swap(ans[s],ans[t]);
s++;
t--;
}
} void Hamilton()
{
int s = ,t; //初始化s取1号点
int k = ;
int i,j,w,tmp;
memset(vis,,sizeof(vis));
for(i=;i<=n;i++)
{
if(mp[s][i])
break;
}
t = i; //取任意连接s的点为t
vis[s] = vis[t] = ;
ans[] = s;
ans[] = t;
while()
{
//从t向外扩展
while()
{
for(i=;i<=n;i++)
{
if(mp[t][i] && !vis[i])
{
ans[k++] = i;
vis[i] = ;
t = i;
break;
}
}
if(i > n)
break;
}
//将当前得到的序列倒置,s和t互换,从t继续扩展,相当于在原来的序列上从s扩展
w = k - ;
i = ;
reverse(ans,i,w);
swap(s,t);
//从新的t向外扩展,相当于在原来的序列上从s向外扩展
while()
{
for(i=;i<=n;i++)
{
if(mp[t][i] && !vis[i])
{
ans[k++] = i;
vis[i] = ;
t = i;
break;
}
}
if(i > n)
break;
}
if(!mp[s][t]) //如果s和t不相邻,进行调整
{
for(i=;i<k-;i++)
{
if(mp[ans[i]][t] && mp[s][ans[i+]]) //取序列中一点i,使得ans[i]与t相连接且ans[i+1]与s相连
break;
}
//将从ans[i+1]到t部分的ans[]倒置
w = k - ;
i++;
t = ans[i];
reverse(ans,i,w);
}
//如果当前s和t相连
if(k == n) //如果当前序列中包含n个元素,算法结束
return;
//当前序列中的元素个数小于n,寻找点ans[i],使得ans[i]与ans[]外一点相连
for(j=;j<=n;j++)
{
if(vis[j])
continue;
for(i=;i<k-;i++)
if(mp[ans[i]][j])
break;
if(mp[ans[i]][j])
break;
}
s = ans[i-];
t = j;
reverse(ans,,i-); //将ans[]中s到ans[i-1]部分的ans[]倒置
reverse(ans,i,k-); //将ans[]中ans[i]到t的部分倒置
ans[k++] = j; //将点j加入到ans[]的尾部
vis[j] = ;
}
} int main()
{
int i,j;
int a,b;
while(scanf("%d%d",&n,&m)!=EOF && (n||m))
{
n *= ;
init();
for(i=;i<=m;i++)
{
scanf("%d%d",&a,&b);
mp[a][b] = mp[b][a] = ; //建立反图
}
Hamilton();
printf("%d",ans[]);
for(i=;i<n;i++)
printf(" %d",ans[i]);
printf("\n");
}
return ;
}

Hamilton回路的判定与构造的更多相关文章

  1. Hamilton回路 旅行商TSP问题 /// dp oj1964

    题目大意: 给出一个n个顶点的无向图,请寻找一条从顶点0出发,遍历其余顶点一次且仅一次.最后回到顶点0的回路——即Hamilton回路. Input 多测试用例.每个测试用例: 第一行,两个正整数 n ...

  2. Islands and Bridges(POJ2288+状压dp+Hamilton 回路)

    题目链接:http://poj.org/problem?id=2288 题目: 题意:求Hamilton 路径权值的最大值,且求出有多少条权值这么大的Hamilton路径. 思路:状压dp,dp[i] ...

  3. Noip2016

    <这篇是以前的,不开新的了,借版面来换了个标题> 高二了 开学一周,每天被文化课作业碾压... 但是仍然阻挡不了想刷题的心情... 对付noip2016的几块:(有点少,以后补) 高精度( ...

  4. Java基础常见英语词汇

    Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的                             ['prəʊɡræmɪŋ]编程 OO: object ...

  5. computer English

    算法常用术语中英对照Data Structures 基本数据结构Dictionaries 字典PriorityQueues 堆Graph Data Structures 图Set Data Struc ...

  6. NOIP算法总结

    前言 离NOIP还有一个星期,匆忙的把寒假整理的算法补充完善,看着当时的整理觉得那时还年少.第二页贴了几张从贴吧里找来的图片,看着就很热血的.旁边的同学都劝我不要再放PASCAL啊什么的了,毕竟我们的 ...

  7. 看到了必须要Mark啊,最全的编程中英文词汇对照汇总(里面有好几个版本的,每个版本从a到d的顺序排列)

    java:  第一章: JDK(Java Development Kit) java开发工具包 JVM(Java Virtual Machine) java虚拟机 Javac  编译命令 java   ...

  8. 冲刺NOIP复习,算法知识点总结

    前言        离NOIP还有一个星期,匆忙的把整理的算法补充完善,看着当时的整理觉得那时还年少.第二页贴了几张从贴吧里找来的图片,看着就很热血的.当年来学这个竞赛就是为了兴趣,感受计算机之美的. ...

  9. 专业英语词汇(Java)

    abstract (关键字)             抽象 ['.bstr.kt] access                            vt.访问,存取 ['.kses]‘(n.入口, ...

随机推荐

  1. Dubbo初探

    Dubbo是什么? 1.阿里巴巴开源项目.2.Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. ps: SOA(面相服务的体系结构) RPC( ...

  2. jquery中的事件与动画

    一:事件 1.鼠标事件 eg:光棒效果 $(function () { $('li').mouseover(function () { //鼠标移过时 $(this).css('background' ...

  3. 汉化入门之ExplorerControls

    第一次汉化,高手勿喷. 01.问题描述 在ArcGIS中有个添加数据窗口,如果在应用程序中直接调用它,则风格一致性则存在问题,很多时间我们都自定义添加数据窗口,我曾经也尝试过.详见ExplorerCo ...

  4. Android 计算布局背景的透明度

    1.#ff000000 此为16进制颜色代码,前2位ff为透明度,后6位为颜色值(000000为黑色,ffffff为白色,可以用ps等软件获取). 2.透明度分为256阶(0-255),计算机上用16 ...

  5. Iterator 迭代器(一)

         迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址.迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为 ...

  6. Android 自定义带刻度的seekbar

    自定义带刻度的seekbar 1.布局 <span style="font-family:SimHei;font-size:18px;"><com.imibaby ...

  7. Android实战--短信发送器

    首先设计界面 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t ...

  8. UI界面的一些简单控件

    虽然都是代码 , 但是基本都有注释. #import "ViewController.h" @interface ViewController () /** * 创建视图 */ @ ...

  9. 关于手机微网站ICP备案

    今天终于拨通了陕西省通信管理局的电话,并告诉对方我们做的是一个化妆品的微网站,会涉及到使用使用支付宝支付. 询问"xxx微网站"网站经营类型,对方告知虽然使用支付宝,但是是微网站, ...

  10. 解决Spring4 MVC请求json数据报406错误

    解决方法一: 1.导入jackson-core-2.5.1.jar和jackson-databind-2.5.1.jar 2.Spring配置文件添加: <!-- 避免IE执行AJAX时,返回J ...