概述
哈密顿图,存在哈密顿回路的图。
哈密顿路径。
1.当度数最小的2个点的度数之和大于等于n时,存在哈密顿路径
poj2438
给定2个人之间有敌对关系,不能坐在一起。
给定有敌对关系的点,求是否存在哈密顿路径?
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 400 + 5;
int mp[maxn][maxn];
int ans[maxn];
int vis[maxn];
int s,t;
int n,m;
int cnt = 0;
void init()
{
memset(ans, 0, sizeof(ans));
memset(vis, 0, sizeof(vis));
cnt = 0;
memset(mp, -1, sizeof(mp));
for(int i = 1;i <= n;i ++) mp[i][i] = 0;
}
void rev(int s,int t)
{
while (s < t) {
swap(ans[s], ans[t]);
s ++,t --;
}
}
void expand()
{
while (1) {
bool fg = 0;
for (int i = 1; i <= n; i ++) {
if(!vis[i] && mp[t][i]){
ans[cnt ++] = i;
t = i;
vis[i] = 1;
fg = 1;
break;
}
}
if(!fg) break;
}
}
void hamilton()
{
s = 1;
for (int i = 1; i <= n; i ++) {//取任意和s相邻的点当做t
if(mp[1][i]){t = i;break;}
}
vis[s] = vis[t] = 1;
ans[0] = s,ans[1] = t;
cnt = 2;
while (1) {
expand();
rev(0, cnt - 1);
swap(s, t);
expand();//从s扩展,翻转ans,交换s和t,再从s扩展
int mid = 0;
if(!mp[s][t]){
for (int i = 1; i < cnt - 2; i ++) {
if(mp[ans[i]][t] && mp[ans[i + 1]][s]){
mid = i + 1;
break;
}
}
rev(mid, cnt - 1);
t = ans[cnt - 1];
}
if(cnt == n) break;
//????
for (int i = 1; i <= n; i ++) {
if(vis[i]) continue;
int j;
for (j = 1; j < cnt - 1; j ++) {
if(mp[ans[j]][i]){mid = j;break;}
}
if(mp[ans[mid]][i]){t = i;mid = j;break;}
}
//???
s = ans[mid - 1];
rev(0, mid - 1);
rev(mid, cnt - 1);
ans[cnt ++] = t;
vis[t] = 1;
}
}
int main()
{
while (scanf("%d%d",&n,&m) != EOF) {
if(n == 0 && m == 0) break;
n *= 2;
int a,b;
init();
for (int i = 0; i < m; i ++) {
scanf("%d%d",&a,&b);
mp[a][b] = mp[b][a] = 0;
}
hamilton();
for (int i = 0; i < cnt; i ++) {
printf("%d%c",ans[i],i == cnt - 1 ? 'n' : ' ');
}
}
return 0;
}
2.竞赛图,为无向完全图中的每条边赋与方向。
n >= 2的时候一定存在哈密顿路径。
hdu3414 求是否存在哈密顿回路
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1000 + 5;
bool mp[maxn][maxn];
int n;
int nex[maxn];
bool expand(int s)
{
memset(nex, -1, sizeof(nex));
int head = s,tail = s;
for (int i = 1; i <= n; i ++) {
if(i == s) continue;
if(mp[i][head]){//i到head有路径就直接添加
nex[i]= head;
head = i;
}
else{//i到head没有路径,那么head到i一定有路径(竞赛图的性质)
int x = head,y = nex[head];
while (y != -1 && mp[y][i]) {//如果y到i有路径就一直向后递归//递归的过程,保证x到i有路径,且在y到i无路径时结束(即i到y有路径)
x = y;
y = nex[y];
}
nex[x] = i; // 将i添加到答案中
nex[i] = y;
if(y == -1) tail = i;//如果x是最后一个,那就将i添至尾部tail
}
}
if(mp[tail][head]){//判断是否是回路
nex[tail] = head;
return true;
}
return false;
}
bool solve()
{
for (int i = 1; i <= n; i ++) {
if(expand(i)) return true;
}
return false;
}
int main()
{
while (scanf("%d",&n) != EOF) {
if(n == 0 ) break;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
scanf("%d",&mp[i][j]);
}
}
if(n == 1) printf("1n");
else if(n == 2 || !solve()) printf("-1n");
else {
int cnt = 0;
for (int p = 1; cnt < n; p = nex[p]) {
cnt ++;
printf("%d%c",p,cnt == n? 'n' : ' ');
}
}
}
return 0;
}
最后
以上就是踏实衬衫为你收集整理的哈密顿图的全部内容,希望文章能够帮你解决哈密顿图所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复