题目描述:
判断一个无向图是否由若干个树(>=3)构成,同时树的根节点构成简单环。
解题报告:
流程如下:
1:判断是否有环,记下上面的点,同时删掉环边,没环直接输出NO
2:再次判断是否有环,有的话输出NO。
3:根据1记下的环上的点,依次作为根节点dfs图,看看遍历的总点数num是否等于n,是的话输出FHTAGN!,否则输出NO
代码如下:
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstdio>
using
namespace std;
int
g[200][200], ans[200], vst[200], dp[200];
int n, m,
num;
vector<int> jeo;
bool
dfs(int id, int deep, int fa)
{
if (vst[id])
{
num = deep - dp[id];
for(int i = dp[id]; i < deep; i++)
jeo.push_back(ans[i]);
for(int i = dp[id] + 1; i < deep; i++)
g[ans[i]][ans[i - 1]] = g[ans[i - 1]][ans[i]] = false;
g[ans[deep - 1]][ans[dp[id]]] = g[ans[dp[id]]][ans[deep - 1]] =
false;
return true;
}
dp[id] = deep;
ans[deep] = id;
vst[id] = true;
for(int i = 1; i <= n; i++) if (g[id][i]
&& i != fa)
if (dfs(i, deep + 1, id)) return true;
return false;
}
void
dfs2(int id, int fa)
{
num++;
for(int i = 1; i <= n; i++) if (g[id][i]
&& i != fa)
dfs2(i, id);
}
int
main()
{
scanf("%d%d", &n, &m);
memset(g, 0, sizeof(g));
while(m--)
{
int a, b;scanf("%d%d", &a,
&b);
g[a][b] = g[b][a] = 1;
}
num = 0;
memset(vst, 0, sizeof(vst));
if (dfs(1, 0, -1))
{
memset(vst, 0, sizeof(vst));
bool flag = false;
for(int i = 1; i <= n; i++) if (!vst[i])
if (dfs(i, 0, -1))
{flag = true; break;}
if (num < 3 || flag) printf("NO\n");
else
{
num = 0; for(int i = 0; i < jeo.size();
i++)
dfs2(jeo[i], -1);
if (num == n) printf("FHTAGN!\n");
else printf("NO\n");
}
}else printf("NO\n");
return 0;
}
加载中,请稍候......