数据结构PTA 基础实验6-2.2 汉密尔顿回路

news/2024/7/15 18:09:24 标签: 数据结构, 算法, 图论

基础实验6-2.2 汉密尔顿回路

  • 题目
  • 解法

题目

著名的“汉密尔顿(Hamilton)回路问题”是要找一个能遍历图中所有顶点的简单回路(即每个顶点只访问 1 次)。本题就要求你判断任一给定的回路是否汉密尔顿回路。

输入格式:
首先第一行给出两个正整数:无向图中顶点数 N(2<N≤200)和边数 M。随后 M 行,每行给出一条边的两个端点,格式为“顶点1 顶点2”,其中顶点从 1 到N 编号。再下一行给出一个正整数 K,是待检验的回路的条数。随后 K 行,每行给出一条待检回路,格式为:
n V1​​ V​2 ⋯ Vn
其中 n 是回路中的顶点数,Vi是路径上的顶点编号。

输出格式:
对每条待检回路,如果是汉密尔顿回路,就在一行中输出"YES",否则输出"NO"。

输入样例:

6 10
6 2
3 4
1 5
2 5
3 1
4 1
1 6
6 3
1 2
4 5
6
7 5 1 4 3 6 2 5
6 5 1 4 3 6 2
9 6 2 1 6 3 4 5 2 6
4 1 2 5 1
7 6 1 3 4 5 2 6
7 6 1 2 5 4 3 1

输出样例:

YES
NO
NO
NO
YES
NO

解法

思路
根据Hamilton回路的特点,一个回路要是Hamilton回路需要具备以下特点:

  1. 它是个回路,即起始点和终止点需要相等。
  2. 它遍历了图上所有的点,且各点只访问一次。
  3. 它中间走过的路径是存在的。

根据以上特点,具体可以这样操作:

  1. 用一个邻接矩阵的结构来存储图的信息
  2. 对于需要判定的回路,首先判断其输入的点是否为Graph->Nv+1,如果不是,直接输出NO,如果是则读取。
  3. 用一个InputArr数组存储输入的点,用Visited数组来标记数组角标对应编号的顶点是否访问。在这一步读入的时候,可以直接去判断输入回路是否满足条件1,当然也可以放在下面的步骤判断。
  4. 每次都用InputArr数组相邻两个元素判断,看这两个元素是否有边相连,一旦没有,输出NO。有的话,把InputArr数组中后一个元素的Visited标记置为1.
  5. 完成后检查Visited的标记是否全为1,如果不全为1就说明不满足条件2,输出NO。

实现

#include<stdio.h>
#include<stdlib.h>

#define MAXN 200
#define INFINITY 100000

typedef int WeightType;
typedef int Vertex;

typedef struct GNode *PtrToGNode;
typedef PtrToGNode MGraph;
struct GNode
{
    int Nv;
    int Ne;
    WeightType G[MAXN][MAXN];
};

typedef struct ENode *PtrToENode;
typedef PtrToENode Edge;
struct ENode
{
    Vertex V1, V2;
    WeightType W;
};

MGraph CreateGraph(int VertexNum)
{
    MGraph Graph = (MGraph)malloc(sizeof(struct GNode));
    Graph->Nv = VertexNum;
    Graph->Ne = 0;

    Vertex i,j;
    for(i=0; i<Graph->Nv; i++)
        for(j=0; j<Graph->Nv; j++)
            Graph->G[i][j] = INFINITY;

    return Graph;
}

void InsertEdge(MGraph Graph, Edge E)
{
    Graph->G[E->V1][E->V2] = E->W;
    Graph->G[E->V2][E->V1] = E->W;
}

MGraph BuildGraph(int VertexNum, int EdgeNum)
{
    MGraph Graph = CreateGraph(VertexNum);
    Graph->Ne = EdgeNum;

    Edge E = (Edge)malloc(sizeof(struct ENode));
    int i;
    for(i=0; i<Graph->Ne; i++)
    {
        scanf("%d %d", &E->V1, &E->V2);
        E->V1--;
        E->V2--;
        E->W = 1;
        InsertEdge(Graph, E);
    }

    return Graph;
}

int IsEdge(MGraph Graph, Vertex V1, Vertex V2)
{
    if(Graph->G[V1][V2] == INFINITY)
        return 0;
    else
        return 1;
}

int main()
{

    int N, M, K, TN, i, j, tmp;
    Vertex InputArr[MAXN+1] = {0};
    int Visited[MAXN] = {0};

    scanf("%d %d", &N, &M);
    MGraph Graph = BuildGraph(N, M);

    scanf("%d", &K);
    for(i=0; i<K; i++)
    {
        scanf("%d", &TN);
        if(TN != Graph->Nv+1)
        {
            printf("NO\n");
            while(TN != 0)
            {
                scanf("%d", &tmp);
                TN--;
            }
        }
        else
        {
            //clear the Visited arr
            for(j=0; j<Graph->Nv; j++)
            {
                Visited[j] = 0;
            }

            //

            for(j=0; j<Graph->Nv+1; j++)
            {
                scanf("%d", &InputArr[j]);
                InputArr[j]--;
            }
            for(j=0; j<Graph->Nv; j++)
            {
                if(IsEdge(Graph, InputArr[j], InputArr[j+1]))
                    Visited[InputArr[j+1]] = 1;
                else
                {
                    printf("NO\n");
                    break;
                }
            }
            if(j == Graph->Nv)
            {
                for(j=0; j<Graph->Nv; j++)
                {
                    if(Visited[j] == 0)
                    {
                        printf("NO\n");
                        break;
                    }
                }
                if(j == Graph->Nv)
                    printf("YES\n");
            }
        }
    }


    return 0;
}


http://www.niftyadmin.cn/n/1399042.html

相关文章

数据结构PTA 进阶实验6-3.4 拯救007(升级版)

进阶实验6-3.4 拯救007&#xff08;升级版&#xff09;题目解法题目 在老电影“007之生死关头”&#xff08;Live and Let Die&#xff09;中有一个情节&#xff0c;007被毒贩抓到一个鳄鱼池中心的小岛上&#xff0c;他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄…

计算机操作系统笔记——操作系统概述

计算机操作系统笔记——操作系统概述1. 什么是操作系统2. 分析OS的功能性需求和非功能性需求2.1 OS的功能性需求2.2 OS的非功能性需求3. 专业术语4. OS的演变、类型及特征5. 一种常见的OS总体结构风格6. 基础平台子系统结构风格7. 双模式基础平台子系统1. 什么是操作系统 这个…

C++函数进阶功能之函数探幽

C函数进阶功能1.内联函数2.引用变量3.默认参数&#xff08;不同的参数数目调用同一个函数&#xff09;4.函数重载&#xff08;相同的函数名调用不同的函数&#xff09;5.函数模板&#xff08;泛型编程&#xff09;6.重载的模板以下未标注的都是C特有的功能1.内联函数 在普通的…

C++函数进阶功能之对象和类

C函数进阶功能类类构造函数析构函数类之间的赋值this指针对象数组关于const的使用以下未标注的都是C特有的功能类是一种用户定义的类型&#xff0c;对象是类的实例。比如int a中&#xff0c;int是类型&#xff0c;a是实例类 类包括类声明和类方法定义两部分。类声明可以类比为…

C++函数进阶功能之使用类

使用类1.运算符重载2.友元3.运算符重载的两种方法4.类的自动转换和强制类型转换以下未标注的都是C特有的功能注意&#xff1a;在类成员函数中&#xff0c;是可以通过运算符&#xff08;.&#xff09;来访问其它对象的私有数据的注意&#xff1a;在涉及到输入输出流的时候&#…

C++函数进阶功能之类和动态内存分配

类和动态内存分配1. 静态存储类2. 类中C自动提供的函数2.1 默认构造函数2.2 复制构造函数2.3 赋值运算符3. 关于返回对象的说明3.1 返回指向const对象的引用3.2 返回指向非const对象的引用3.3 返回对象3.4 返回const对象4. 使用指向对象的指针5. 转换函数以下未标注的都是C特有…

C++函数进阶功能之类继承

类继承1. 成员初始化列表的作用2. 公有派生2.1 派生类的构造函数2.2 派生类的析构函数2.3 派生类和基类之间的特殊关系2.4 公有继承的本质与缺陷2.5 多态公有继承3. 静态联编和动态联编4. 保护成员&#xff1a;protected5. 抽象基类6. 继承和动态内存分配6.1 动态内存分配6.2 友…

计算机组成原理知识总结——输入输出系统篇

输入输出系统1.概述1.1 I/O的发展概况1.2 输入输出系统的组成1.3 I/O设备与主机的联系方式1.4 I/O设备与主机信息传送的控制方式2. I/O设备3. I/O接口3.1 概述3.2 接口的功能和组成4. 程序查询方式5. 程序中断方式5.1 程序中断方式的接口电路5.2 中断服务程序的流程6. DMA方式6…