1122 Hamiltonian Cycle (25 分)
水~。
题意
给定一个无向图和一.堆路径,判断每一条路径是否是这个无向图的哈密顿回路。所谓哈密顿回路是指首尾结点相同、经过且恰好经过图上所有结点各一次的路径。
思路
根据哈密顿回路的定义,一条路径是哈密顿回路需要满足3个条件:
(1)首尾结点相同。
(2)路径的每条边必须都存在。
(3)不考虑首结点,路径的剩余结点包含且只包含图中所有结点各1次。
为了方便编码,条件(3)可以等价于同时满足以下两个条件:
(3.1)路径的结点个数num等于图的结点个数n加1。
(3.2)不考虑首结点,路径的剩余结点互不相同。
由此可以得到下面的算法过程。
-
令bool型二维数组G表示无向图,输入所有无向边u->v,令G[u][v]= G[v][u] = true。
-
对单条路径path,如果path上的结点个数不等于图的结点个数加1、或者路径的首尾结点不同,那么返回false,表示非哈密顿回路。之后,定义bool型数组vis,记录结点是否已经在路径上被遍历过,初始化均为false。
-
接下来遍历路径path除首结点外的的剩余结点:
(1)如果路径的上一结点与当前结点形成的边在图中不存在,说明非哈密顿回路,返回false。对当前遍历到的结点,令其vis值为true,表示其已在路径上被遍历过。
(2)遍历vis数组,判断是否有结点未在路径上出现过(vis的对应值为fales),那么说明除首结点外有重复结点,该路径不是哈密顿回路,返回false。 -
根据返回的结果是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;
}