ZJU PTA ds 7-1 Hamiltonian Cycle

7-1 Hamiltonian Cycle

The “Hamilton cycle problem” is to find a simple cycle that contains every vertex in a graph. Such a cycle is called a “Hamiltonian cycle”.

In this problem, you are supposed to tell if a given cycle is a Hamiltonian cycle.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers N ( 2 < N ≤ 200 ) N (2<N≤200) N(2<N200), the number of vertices, and M M M, the number of edges in an undirected graph. Then M M M lines follow, each describes an edge in the format Vertex1 Vertex2, where the vertices are numbered from 1 to N N N. The next line gives a positive integer K K K which is the number of queries, followed by K K K lines of queries, each in the format:

n   V 1   V 2   . . .   V n n \ V_1\ V_2\ ... \ V_ n n V1 V2 ... Vn

where n is the number of vertices in the list, and V i ′ s V _i's Vis are the vertices on a path.

Output Specification:

For each query, print in a line YES if the path does form a Hamiltonian cycle, or NO if not.

Sample Input:

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

Sample Output:

YES
NO
NO
NO
YES
NO
#include <stdio.h>
#include <string.h>

#define MAXN 201

typedef enum {false, true} bool;

int G[MAXN][MAXN] = {0};
int Ne = 0, Nv = 0;

void BuildGraph(void);
bool IsHamiltonianCycle(int *v, int n);

int main()
{
    // 建立图,用邻接矩阵还是用邻接表?
    // 依据操作,判断两个节点之间是否存在边,并且每一个节点是否只经过一次
    BuildGraph();
    
    int k;
    scanf("%d", &k);
    
    for (int i = 0; i < k; i++) {
        int n;
        scanf("%d", &n);
        int v[n + 1];
        for (int j = 1; j <= n; j++) {
            scanf("%d", &v[j]);
            // printf("v[%d] = %d ", j, v[j]);
        }
        if (IsHamiltonianCycle(v, n) == true) {
            puts("YES");
        }
        else {
            puts("NO");
        }
    }
    
    return 0;
}

void BuildGraph(void)
{
    scanf("%d%d", &Nv, &Ne);

    int v1, v2;
    for (int i = 1; i <= Ne; i++) {
        scanf("%d%d", &v1, &v2);
        G[v1][v2] = 1;
        ///
        G[v2][v1] = 1;
    }
    
}

// 判断是否是哈密顿回路
// 给定k和一些数,判断
// 哈密顿回路需要满足以下条件
// 1. 第一个数肯定等于节点数 + 1
// 2. 第一个节点和最后一个节点相同
// 3. 第一个至K-1个节点必须遍历所有的K-1(即n)个节点,如果发现有重复,可break
bool IsHamiltonianCycle(int *vertices, int n)
{
    if (n != Nv + 1) {
        return false;
    }
    
    // vertices从1开始
    if (vertices[1] != vertices[n]) {
        return false;
    }
    // printf("here1 n=%d   ", n);
    // vertices[1]与vertices[n]首尾相等
    int visit[n + 1];
    memset(visit, 0, sizeof(visit));
    // for (int j = 1; j <= n; j++) {
    //     printf("%d ", visit[j]);
    // }
    int i = 1;
    while (i != n) {
        int v1 = vertices[i];
        int v2 = vertices[i + 1];
        // printf("G[%d][%d] = %d visit[v1] = %d   ", v1, v2,G[v1][v2], visit[v1]);
        if (G[v1][v2] == 1 && visit[v1] == 0) {
            visit[v1] = 1;
            i++;
            continue;
        }
        else {
            return false;
        }
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值