POJ 2438 哈密顿回路
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 4730 | Accepted: 754 | Special Judge |
Description
Now we assume that there are 2 * n children who sit around a big table, and that none has more than n - 1 "enemies".
Input
There will be a blank line between input blocks. And m = n = 0 indicates the end of input and this case shouldn't be processed.
Output
Sample Input
1 0 2 2
1 2
3 4 3 6
1 2
1 3
2 4
3 5
4 6
5 6 4 12
1 2
1 3
1 4
2 5
2 6
3 7
3 8
4 8
4 7
5 6
5 7
6 8 0 0
Sample Output
1 2
4 2 3 1
1 6 3 2 5 4
1 6 7 2 3 4 5 8
解析 题目说保证 每个点的度数等于n所以 一定存在哈密顿回路 然后在他给出的图的补图上求一个哈密顿回路就可以了 套一个O(n*n)的板子。
哈密顿图:存在哈密顿回路的图
哈密顿图的判定:
一:Dirac定理(充分条件)
设一个无向图中有N个顶点,若所有顶点的度数大于等于N/2,则哈密顿回路一定存在.(N/2指的是⌈N/2⌉,向上取整)
二:基本的必要条件
设图G=<V, E>是哈密顿图,则对于v的任意一个非空子集S,若以|S|表示S中元素的数目,G-S表示G中删除了S中的点以及这些点所关联的边后得到的子图,则W(G-S)<=|S|成立.其中W(G-S)是G-S中联通分支数.
三:竞赛图(哈密顿通路)
N(N>=2)阶竞赛图一点存在哈密顿通路.
AC代码
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn = +;
bool visit[maxn];
int mapp[maxn][maxn],ans[maxn];
int n,m;
inline void _reverse(int s, int t) //将数组anv从下标s到t的部分的顺序反向
{
int temp;
while(s < t)
{
temp = ans[s];
ans[s] = ans[t];
ans[t] = temp;
s++;
t--;
}
}
void Hamilton(int n)
{
memset(visit,false,sizeof(visit));
int s = , t;//初始化取s为1号点
int ansi = ;
int i, j;
int w;
int temp;
for(i = ; i <= n; i++) if(mapp[s][i]) break;
t = i;//取任意邻接与s的点为t
visit[s] = visit[t] = true;
ans[] = s;
ans[] = t;
while(true)
{
while(true) //从t向外扩展
{
for(i = ; i <= n; i++)
{
if(mapp[t][i] && !visit[i])
{
ans[ansi++] = i;
visit[i] = true;
t = i;
break;
}
}
if(i > n) break;
}
w = ansi - ;//将当前得到的序列倒置,s和t互换,从t继续扩展,相当于在原来的序列上从s向外扩展
i = ;
_reverse(i, w);
temp = s;
s = t;
t = temp;
while(true) //从新的t继续向外扩展,相当于在原来的序列上从s向外扩展
{
for(i = ; i <= n; i++)
{
if(mapp[t][i] && !visit[i])
{
ans[ansi++] = i;
visit[i] = true;
t = i;
break;
}
}
if(i > n) break;
}
if(!mapp[s][t]) //如果s和t不相邻,进行调整
{
for(i = ; i < ansi - ; i++)//取序列中的一点i,使得ans[i]与t相连,并且ans[i+1]与s相连
if(mapp[ans[i]][t] && mapp[s][ans[i + ]])break;
w = ansi - ;
i++;
t = ans[i];
_reverse(i, w);//将从ans[i +1]到t部分的ans[]倒置
}//此时s和t相连
if(ansi == n) return;//如果当前序列包含n个元素,算法结束
for(j = ; j <= n; j++) //当前序列中元素的个数小于n,寻找点ans[i],使得ans[i]与ans[]外的一个点相连
{
if(visit[j]) continue;
for(i = ; i < ansi - ; i++)if(mapp[ans[i]][j])break;
if(mapp[ans[i]][j]) break;
}
s = ans[i - ];
t = j;//将新找到的点j赋给t
_reverse(, i - );//将ans[]中s到ans[i-1]的部分倒置
_reverse(i, ansi - );//将ans[]中ans[i]到t的部分倒置
ans[ansi++] = j;//将点j加入到ans[]尾部
visit[j] = true;
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==)break;
n*=;
memset(mapp,,sizeof(mapp));
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
mapp[i][j]=i==j?:;
for(int i=;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
mapp[u][v]=mapp[v][u]=;
}
Hamilton(n);
printf("%d",ans[]);
for(int i=;i<=n-;i++)
{
printf(" %d",ans[i]);
}
printf("\n");
}
}
该算法的详细过程及哈密顿回路的其他知识
https://www.cnblogs.com/Ash-ly/p/5452580.html
POJ 2438 哈密顿回路的更多相关文章
- POJ 2438 Children's Dining(哈密顿回路)
题目链接:http://poj.org/problem?id=2438 本文链接:http://www.cnblogs.com/Ash-ly/p/5452615.html 题意: 有2*N个小朋友要坐 ...
- POJ 2438 (哈密顿回路)
分析: 2*n个小朋友,每个最多有n-1个"敌人",显然是存在哈密顿回路的. 预处理边,然后找哈密顿回路. code #include <iostream> #incl ...
- poj 2438 Children's Dining
http://poj.org/problem?id=2438 题意: 有2*N个人要坐在一张圆桌上吃饭,有的人之间存在敌对关系,安排一个座位次序,使得敌对的人不相邻. 假设每个人最多有N-1个敌人.如 ...
- POJ 2438 Children’s Dining (哈密顿图模板题之巧妙建反图 )
题目链接 Description Usually children in kindergarten like to quarrel with each other. This situation an ...
- Hamilton回路的判定与构造
定理1:在一个具有n个顶点的无向连通图G中,如果任意两个顶点的度数之和大于n,则G具有Hamilton回路.此条件为充分条件 定理2:设图G = <V,E>,是Hamilton图,则对于v ...
- Ouroboros Snake POJ - 1392(数位哈密顿回路)
看hdu 2894的题意 两个题一样 旋转鼓的表面分成m块扇形,如图所示(m=8).图中阴影区表示用导电材料制成,空白区用绝缘材料制成,终端a.b和c是3(k=3)处接地或不是接地分别用二进制信号0 ...
- POJ 3301 Texas Trip (三分)
题目链接 题意 : 给你若干个点,让你找最小的正方形覆盖这所有的点.输出面积. 思路 : 三分枚举正方形两对边的距离,然后求出最大,本题用的是旋转正方形,也可以用旋转点,即点的相对位置不变. 正方形从 ...
- 【转】欧拉回路&特殊图下的哈密顿回路题集
转自:http://blog.csdn.net/shahdza/article/details/7779385 欧拉回路[HDU]1878 欧拉回路 判断3018 Ant Trip 一笔画问题1116 ...
- 【POJ】【1739】Tony's Tour
插头DP 楼教主男人八题之一! 要求从左下角走到右下角的哈密顿路径数量. 啊嘞,我只会求哈密顿回路啊……这可怎么搞…… 容易想到:要是把起点和重点直接连上就变成一条回路了……那么我们就连一下~ 我们可 ...
随机推荐
- asp.net mvc 5 微信接入VB版 - 获取AccessToken
获取AccessToken是微信接入的又一个基础操作.很多微信接口需要这个2小时一刷新的AccessToken作为参数. 转载请说明作者Nukepayload2 首先根据开发文档把获取AccessTo ...
- help命令
help——获得Shell内置命令的帮助信息 命令所在路径:Shell内置命令 示例1: # help cd 使用which或者whereis查找不到路径的命令一般是Shell内置命令,cd就是一个S ...
- HALCON算子1
https://blog.csdn.net/think_fast/article/details/7011364 待验证学习
- 聊天室(C++客户端+Pyhton服务器)3.群功能添加
创建群 数据库 group_table(user, name) grpuser_table(grpname,user) 按下添加群按钮 // 创建群组void CUserDialog::OnBnCli ...
- dialog - 从 shell 显示对话框
总览 (SYNOPSIS) dialog --clear dialog --create-rc file dialog --print-maxsize dialog common-options bo ...
- class 写在 import的位置 类的名字第一个字母大写 后面没括号 ES6
class 写在 import的位置 类的名字第一个字母大写 后面没括号 class ObTableDataClass {}或者 const ObTableDataClass = class { in ...
- LCIS 最长上升公共子序列问题
首先点名一个串叫 L1,另一个叫L2. 明显的是一个DP,那么我们来探讨下如何求得答案. 朴素的算法 首先我们定义状态$dp[ i ][ j ]$表示L1中前i个与L2中前j个的最长公共上升子序列. ...
- 深搜DFS
POJ-1321 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有 ...
- MyBatis的动态sql小练习,小回顾
关键字if+trim trim可以去除多余的关键字,是where和set的组合 trim标记是一个格式化的标记,可以完成set或者是where标记的功能,如下代码: <trim prefix=& ...
- 【MySQL】索引和锁
前言 本文摘自数据库两大神器[索引和锁] 声明:如果没有说明具体的数据库和存储引擎,默认指的是MySQL中的InnoDB存储引擎 索引 在之前,我对索引有以下的认知: 索引可以加快数据库的检索速度 表 ...