题意:
给你n个点m条边的无向图(无重边和自环),问你是否存在一个简单的环且环上的点都是某棵树的树根。
思路:
注意这句话:an undirected graph that can be represented as a set of three or more rooted trees, whose roots are connected by a simple cycle.也就是说首先我们要判断给出的无向图是否只有一块连通块。这里我用并查集来判断连通块个数,然后DFS一遍去找是否存在唯一的环(根据简单环的定义)。其实这里不用DFS去找是否有简单环,直接用n==m判断是否有简单环就可以Orz。。。。。。当时没想那么多直接暴力搞。。。。。
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int MAX=105;
bool vis[MAX],edge[MAX][MAX],use[MAX];
vector<int> gr[MAX];
int n,m,num,fa[MAX];
void init(){
for(int i=1;i<=n;i++){
fa[i]=i;
}
}
int Find(int x){
int r=x,t;
while(r!=fa[r]){
r=fa[r];
}
while(x!=r){
t=fa[x];
fa[x]=r;
x=t;
}
return r;
}
void Union(int u,int v){
int a=Find(u);
int b=Find(v);
if(a!=b){
fa[a]=b;
}
}
void DFS(int u){
for(int i=0;i<gr[u].size();i++){
int v=gr[u][i];
if(vis[v]&&edge[u][v]==false){
num++;
return;
}
if(vis[v]==false&&edge[u][v]==false){
edge[u][v]=edge[v][u]=true;
vis[v]=true;
DFS(v);
vis[v]=false;
}
}
}
int main(){
scanf("%d%d",&n,&m);
int u,v;
init();
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
Union(u,v);
gr[u].push_back(v);
gr[v].push_back(u);
}
memset(vis,false,sizeof(vis));
memset(edge,false,sizeof(edge));
memset(use,false,sizeof(use));
int cnt=0;
for(int i=1;i<=n;i++){
int p=Find(i);
if(use[p]) continue;
use[p]=true;
cnt++;
}
if(cnt==1){
num=0;
int p=Find(1);
vis[p]=true;
DFS(p);
if(num==1) printf("FHTAGN!\n");
else printf("NO\n");
}
else printf("NO\n");
return 0;
}