关闭

[置顶] 汉密尔顿回路问题

标签: 汉密尔顿回路数据结构
911人阅读 评论(0) 收藏 举报
分类:

概述

这是自己这学期算法课的实验作业。下面给出汉密尔顿图的定义。定义如下:对于连通图G=(V,E),V1,V2,…,Vn是G 的一条通路,且图中任意两个顶点都可达,若 中每个顶点在该通路中出现且仅出现一次,则称该通路为汉密尔顿通路。若 V1=Vn,则称该通路为汉密尔顿回路。


算法描述

1)初始化最佳路径数组best_path,同时初始化临时路径数组path与访问数组isvisited,设置最小长度min,设置长度变量length = 0
2)开始对每个顶点进行遍历寻找最佳路径,首先堆访问数组中对应顶点进行置1,并把当前顶点追加到path,同时利用cur_vertex这个临时变量保存当前结点,并开始进行循环。
3)找到出cur_vertex之外与之相邻且并未访问的一个顶点k,利用tmp保存这两点之间的权重,之后检查是否存在比tmp更小且与cur_vertex相邻的顶点,如有则更新tmp与访问的顶点k,之后更新length += tmp,以及更新cur_vertex = k,如果length大于min,则说明改路径无效,跳出循环。
4)重复步骤3遍历每一个结点。循环结束后,对length更新,加上最后一个结点到cur_vertex结点的距离。这是如果min大于legnth,则对min更新,并把path数组复制到best_path中去。
5)重复步骤2)直至遍历完每个结点。返回最小长度。

//求汉密尔顿回路函数 
int Hanmilton(){
    int path[1000] = {0};
    int cur_vertex = 0;     //作为保存当前结点 
    int length = 0;         //汉密尔顿回路长度
    int min = 10000;        //最小长度 
    for(int i = 1 ; i < this->Nv+1 ; i++){//对每个顶点为初始点进行比遍历寻找汉密尔顿回路 
        length = 0;     //重新设置最端长度为0 
        memset(this->isvisited,0,sizeof(this->isvisited[0])*(this->Nv+1));  //重新初始化访问数组为0 
        this->isvisited[i] = 1;     //标记当前结点为已访问 
        path[1] = i;        //保存到临时路径数组的第一个
        cur_vertex = i;     //保存当前顶点
        for(int j = 2 ; j < this->Nv+1 ; j++){//访问剩余的结点 
            int k = 0;
            //寻找到第一个未访问的结点 
            for(k = 2 ; k < this->Nv+1 ; k++){
                if(this->isvisited[k] == 0){
                    break;
                }
            }
            int tmp = this->data[cur_vertex][k];        //保存当前顶点到该结点的路径长度 
            for(int m = k+1 ; m < this->Nv+1 ; m++){//向后寻找有没有路径更短的节点 
                if((!this->isvisited[m]) && (tmp > this->data[cur_vertex][m])){
                    tmp = this->data[cur_vertex][m];//更新当前最短路径 
                    k = m;//更新第一个未被访问的结点 
                }
            }
            path[j] = k;    //保存路径上的结点
            this->isvisited[k] = 1; //标记为已访问 
            cur_vertex = k;     //跟新当前结点 
            length += tmp;      //跟新长度 
            if(length > min){   //当前长度大于最小长度,则改路径无效,跳出循环 
                break;
            }
        }
        length += this->data[cur_vertex][i];
        if(min > length){       //更新最小长度并保存最佳路径 
            min = length;
            for(int m = 0 ; m < this->Nv+1 ; m++){
                this->best_path[m] = path[m]; 
            }
        }
    }
    //返回最小长度 
    return min;
}

例子

下面的例子是基于如下图结构:
这里写图片描述
全部代码如下:

#include <iostream>
#include <cstring> 
#include <vector>
#include <cstdio>
using namespace std;

/*
    边与边长:(起点,终点,长度) 
    1 2 2
    1 3 3
    1 4 2
    1 5 5
    2 3 6
    2 4 8
    2 5 10
    3 4 10
    3 5 15
    4 5 12 
*/ 

class Graph{
    private:
        int** data;     //邻接矩阵 到sa 拉黑圣诞节,  
        int* isvisited; //访问数组 
        int Nv;         //顶点数 
        int Ne;         //边数
        vector<int> best_path;  //汉密尔顿最佳路径 
    public:
        //构造函数
        Graph(int nv,int ne){
            this->Nv = nv;
            this->Ne = ne;
            this->data = new int*[nv+1];
            best_path.reserve(nv+1);
            for(int i = 0 ; i < nv+1 ; i++){
                best_path[i] = 0;
            }
            //初始化访问数组 
            this->isvisited = new int[nv+1];
            memset(this->isvisited,0,sizeof(this->isvisited[0])*(nv+1));
            //对邻接矩阵进行初始化 
            for(int i = 0 ; i < nv+1 ; i++){
                data[i] = new int[nv+1];
                memset(data[i],0,sizeof(data[i][0])*(nv+1));
            }
            cout<<"请输入边与边长:"<<endl;
            //对边进行初始化 
            for(int i = 0 ; i < ne ; i++){
                int v1,v2,weight;
                cin>>v1>>v2>>weight;
                this->data[v1][v2] = this->data[v2][v1] = weight;
            } 
        }

        //求汉密尔顿回路函数 
        int Hanmilton(){
            int path[1000] = {0};
            int cur_vertex = 0;     //作为保存当前结点 
            int length = 0;         //汉密尔顿回路长度
            int min = 10000;        //最小长度 
            for(int i = 1 ; i < this->Nv+1 ; i++){//对每个顶点为初始点进行比遍历寻找汉密尔顿回路 
                length = 0;     //重新设置最端长度为0 
                memset(this->isvisited,0,sizeof(this->isvisited[0])*(this->Nv+1));  //重新初始化访问数组为0 
                this->isvisited[i] = 1;     //标记当前结点为已访问 
                path[1] = i;        //保存到临时路径数组的第一个
                cur_vertex = i;     //保存当前顶点
                for(int j = 2 ; j < this->Nv+1 ; j++){//访问剩余的结点 
                    int k = 0;
                    //寻找到第一个未访问的结点 
                    for(k = 2 ; k < this->Nv+1 ; k++){
                        if(this->isvisited[k] == 0){
                            break;
                        }
                    }
                    int tmp = this->data[cur_vertex][k];        //保存当前顶点到该结点的路径长度 
                    for(int m = k+1 ; m < this->Nv+1 ; m++){//向后寻找有没有路径更短的节点 
                        if((!this->isvisited[m]) && (tmp > this->data[cur_vertex][m])){
                            tmp = this->data[cur_vertex][m];//更新当前最短路径 
                            k = m;//更新第一个未被访问的结点 
                        }
                    }
                    path[j] = k;    //保存路径上的结点
                    this->isvisited[k] = 1; //标记为已访问 
                    cur_vertex = k;     //跟新当前结点 
                    length += tmp;      //跟新长度 
                    if(length > min){   //当前长度大于最小长度,则改路径无效,跳出循环 
                        break;
                    }
                }
                length += this->data[cur_vertex][i];
                if(min > length){       //更新最小长度并保存最佳路径 
                    min = length;
                    for(int m = 0 ; m < this->Nv+1 ; m++){
                        this->best_path[m] = path[m]; 
                    }
                }
            }
            //返回最小长度 
            return min;
        }

        //打印最佳汉密尔顿回路 
        void Print_Best_Path(){
            cout<<this->best_path[1];
            for(int i = 2 ; i < this->Nv+1 ; i++){
                cout<<" -> "<<this->best_path[i];
            }
            cout<<" -> "<<this->best_path[1];
        }

        //打印邻接矩阵 
        void Print(){
            for(int i = 1 ; i < this->Nv+1 ; i++){
                for(int j = 1 ; j < this->Nv+1 ; j++){
                    printf("%3d",this->data[i][j]);
                }
                cout<<endl;
            }
        }
};

int main()
{
    cout<<"请输入顶点数与边数:"<<endl;
    int nv,ne;
    cin>>nv>>ne;
    Graph graph(nv,ne);
    cout<<"邻接矩阵为:"<<endl;
    graph.Print();
    cout<<"该图的汉密尔顿回路长度为:"<<endl;
    int length = 0;
    length = graph.Hanmilton();
    cout<<length<<endl;
    cout<<"汉密尔顿回路路径为:"<<endl;
    graph.Print_Best_Path(); 

    return 0;
}

运行结果如下:
这里写图片描述

1
0
查看评论

汉密尔顿回路求解

汉密尔顿通路:给定图G,若存在一条经过图中的每个顶点一次且仅一次的通路,则称这条 通路为汉密尔顿通路。 汉密尔顿回路:若存在一条回路,经过图中的每个顶点一次且仅一次,则 称这条回路为汉密尔顿回路。 汉密尔顿图:具有汉密尔顿回路的图称为汉密尔顿图。 zoj 2398 poj 22...
  • u011699990
  • u011699990
  • 2014-11-28 20:25
  • 2335

欧拉回路和哈密尔顿回路

“哈密尔顿回路问题”与“欧拉回路问题”看上去十分相似,然而却是完全不同的两个问题。“哈密尔顿回路问题”是访问除原出发结点以外的每个结点一次且仅一次(图2有哈密尔顿回路,如B到C到A到D再到B就是一个回路),而“欧拉回路问题”是访问每条边一次且仅一次;对任一给定的图是否存在“欧拉回路”欧拉已给出了充分...
  • sunmenggmail
  • sunmenggmail
  • 2012-12-04 21:56
  • 5848

系分知识点-图-欧拉回路和汉米尔顿回路

  关于欧拉路径 汉密尔顿路径 以及其他 如果给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,这条条路称为欧拉路;若存在一条回路,经过图中每边一次且仅一次,那么该回路称为欧拉回路。存在欧拉回路的图,称为欧拉图。对于无向图G,具有一条欧拉路,当且仅当G是连通的,且有零个或两个奇数...
  • big_worm
  • big_worm
  • 2007-07-23 13:12
  • 1760

hdu 4337——poj 2438(哈密尔顿回路求解模板)

转:http://imlazy.ycool.com/post.2072698.html   Dirac 定理:设一个无向图中有 N 个节点,若所有节点的度数都大于等于 N/2,则汉密尔顿回路一定存在。注意,“N/2” 中的除法不是整除,而是实数除法。如果 N 是偶数,当然没有歧...
  • Weiguang_123
  • Weiguang_123
  • 2012-08-04 14:03
  • 3717

【NPC】11、汉密尔顿路径规约到汉密尔顿回路

  • xiazdong
  • xiazdong
  • 2012-12-10 09:02
  • 3026

汉密尔顿回路问题

概述这是自己这学期算法课的实验作业。下面给出汉密尔顿图的定义。定义如下:对于连通图G=(V,E),V1,V2,…,Vn是G 的一条通路,且图中任意两个顶点都可达,若 中每个顶点在该通路中出现且仅出现一次,则称该通路为汉密尔顿通路。若 V1=Vn,则称该通路为汉密尔顿回路。算法描述1)初始化最佳路径数...
  • qq_30091945
  • qq_30091945
  • 2017-09-12 10:38
  • 911

汉密尔顿回路C语言贪婪算法

  • 2013-01-25 23:59
  • 7KB
  • 下载

汉密尔顿回路 汉密尔顿圈经典算法 MATLAB程序实现

  • 2009-08-16 14:43
  • 15KB
  • 下载

最小汉密尔顿回路问题 状态压缩dp

给定n个顶点做成的图,要求从顶点0出发经过所有点一次然后回到0点的一条权值之和最小的一条路的权值 #include #include #include #include #include #include #include #include #include #include #...
  • qq_24667639
  • qq_24667639
  • 2015-05-01 21:07
  • 467

【NPC】23、有向汉密尔顿回路规约到无向汉密尔顿回路

  • xiazdong
  • xiazdong
  • 2012-12-18 20:32
  • 1872
    个人资料
    • 访问:155559次
    • 积分:4927
    • 等级:
    • 排名:第6843名
    • 原创:329篇
    • 转载:0篇
    • 译文:0篇
    • 评论:80条
    博客专栏
    最新评论