1122 Hamiltonian Cycle (25 分)

水~。

题意

给定一个无向图和一.堆路径,判断每一条路径是否是这个无向图的哈密顿回路。所谓哈密顿回路是指首尾结点相同、经过且恰好经过图上所有结点各一次的路径。

思路

根据哈密顿回路的定义,一条路径是哈密顿回路需要满足3个条件:
(1)首尾结点相同。
(2)路径的每条边必须都存在。
(3)不考虑首结点,路径的剩余结点包含且只包含图中所有结点各1次。

为了方便编码,条件(3)可以等价于同时满足以下两个条件:
(3.1)路径的结点个数num等于图的结点个数n加1。
(3.2)不考虑首结点,路径的剩余结点互不相同。
由此可以得到下面的算法过程。

  1. 令bool型二维数组G表示无向图,输入所有无向边u->v,令G[u][v]= G[v][u] = true。

  2. 对单条路径path,如果path上的结点个数不等于图的结点个数加1、或者路径的首尾结点不同,那么返回false,表示非哈密顿回路。之后,定义bool型数组vis,记录结点是否已经在路径上被遍历过,初始化均为false。

  3. 接下来遍历路径path除首结点外的的剩余结点:
    (1)如果路径的上一结点与当前结点形成的边在图中不存在,说明非哈密顿回路,返回false。对当前遍历到的结点,令其vis值为true,表示其已在路径上被遍历过。
    (2)遍历vis数组,判断是否有结点未在路径上出现过(vis的对应值为fales),那么说明除首结点外有重复结点,该路径不是哈密顿回路,返回false。

  4. 根据返回的结果是true还是false输出YES或者NO即可。

const int N=210;
bool g[N][N];
bool vis[N];
int n,m,q,k;

bool check(vector<int> &v)
{
    if(v[0] != v[k-1] || k != n+1) return false;

    memset(vis,0,sizeof vis);
    for(int i=0;i<k-1;i++)
    {
        int a=v[i],b=v[i+1];
        vis[a]=true;
        if(!g[a][b]) return false;
    }

    for(int i=1;i<=n;i++)
        if(!vis[i])
            return false;

    return true;
}

int main()
{
    cin>>n>>m;

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

    cin>>q;
    while(q--)
    {
        memset(vis,0,sizeof vis);

        cin>>k;
        vector<int> v(k);
        for(int i=0;i<k;i++) cin>>v[i];

        bool ok=check(v);
        if(ok) puts("YES");
        else puts("NO");
    }
    //system("pause");
    return 0;
}
posted @ 2021-03-02 11:45  Dazzling!  阅读(44)  评论(0编辑  收藏  举报