AcWing 1615:哈密顿回路 ← Hamilton 回路

【题目来源】
https://www.acwing.com/problem/content/1617/

【题目描述】
哈密顿回路问题是找到一个包含图中每个顶点的简单回路。
这样的回路称为“哈密顿回路”。
在本题中,你需要做的是判断给定路径是否为哈密顿回路。

【输入格式】
第一行包含一个整数 N 表示顶点数,一个整数 M 表示给定无向图中的边数。
接下来 M 行,每行包含两个整数 a,b,表示点 a 和 b 之间存在一条边。
所有顶点编号从 1 到 N。
再一行给出整数 K,表示询问次数。
接下来 K 行,每行包含一个询问,格式如下:
n  V1  V2  …  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​​​​​​​

【数据范围】
2<N≤200,
N−1≤M≤N(N−1)/2,
1≤K≤1000,
1≤n≤410

【算法分析】
● Hamilton 回路,是经过图中每个顶点恰好一次并能回到起点的闭合路径。
● 欧拉回路,是经过图中每条边恰好一次并能回到起点的闭合路径(顶点可重复访问)。
● 一个路径是哈密顿回路,必须同时满足:
(1)路径长度 = n+1(n 个顶点各走一次,最后回到起点,多一步)
(2)起点 = 终点
(3)所有顶点都被访问到
(4)中间每个顶点只出现一次
(5)​​​​​​​​​​​​​​相邻两个顶点之间必须有边

【算法代码】

#include <bits/stdc++.h>
using namespace std;

const int N=2e2+5;
int g[N][N];
bool st[N];
int val[N<<1];
int n,m;

bool check(int cnt) {
    memset(st,0,sizeof st);
    if(cnt!=n+1) return 0;
    if(val[1]!=val[cnt]) return 0;

    for(int i=1; i<cnt; i++) {
        int u=val[i],v=val[i+1];
        if(st[u]) return 0;
        if(!g[u][v]) return 0;
        st[u]=1;
    }

    for(int i=1; i<=n; i++) {
        if(!st[i]) return 0;
    }

    return 1;
}

int main() {
    cin>>n>>m;
    while(m--) {
        int a,b;
        cin>>a>>b;
        g[a][b]=g[b][a]=1;
    }

    int T;
    cin>>T;
    while(T--) {
        int cnt;
        cin>>cnt;
        for(int i=1; i<=cnt; i++) cin>>val[i];

        if(check(cnt)) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }

    return 0;
}

/*
in:
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

out:
YES
NO
NO
NO
YES
NO
*/



【参考文献】
https://www.acwing.com/solution/content/85416/
https://www.acwing.com/solution/content/287515/


 

posted @ 2026-05-13 07:00  Triwa  阅读(21)  评论(0)    收藏  举报