Codeforces 103B. Cthulhu 寻找奈亚子

本文深入探讨了一种独特且复杂的图论问题,涉及到Cthulhu这一神秘生物与全球超级大国Pentagon之间的隐秘联系。通过分析一个含有n个顶点和m条边的无向图,揭示了如何判断该图是否能被视作Cthulhu的形象。Cthulhu形象的解析不仅涉及到图的结构分析,还融入了抽象的数学逻辑和丰富的想象力。文章详细介绍了判断条件和算法过程,旨在帮助读者理解这一看似荒诞却又充满逻辑的数学问题,同时揭示了隐藏在科学与幻想交织背后的深层思考。

B. Cthulhu
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

...Once upon a time a man came to the sea. The sea was stormy and dark. The man started to call for the little mermaid to appear but alas, he only woke up Cthulhu...

Whereas on the other end of the world Pentagon is actively collecting information trying to predict the monster's behavior and preparing the secret super weapon. Due to high seismic activity and poor weather conditions the satellites haven't yet been able to make clear shots of the monster. The analysis of the first shot resulted in an undirected graph with n vertices and m edges. Now the world's best minds are about to determine whether this graph can be regarded as Cthulhu or not.

To add simplicity, let's suppose that Cthulhu looks from the space like some spherical body with tentacles attached to it. Formally, we shall regard as Cthulhu such an undirected graph that can be represented as a set of three or more rooted trees, whose roots are connected by a simple cycle.

It is guaranteed that the graph contains no multiple edges and self-loops.

Input

The first line contains two integers — the number of vertices n and the number of edges m of the graph (1 ≤ n ≤ 1000 ≤ m ≤ ).

Each of the following m lines contains a pair of integers x and y, that show that an edge exists between vertices x and y (1 ≤ x, y ≤ n, x ≠ y). For each pair of vertices there will be at most one edge between them, no edge connects a vertex to itself.

Output

Print "NO", if the graph is not Cthulhu and "FHTAGN!" if it is.

Sample test(s)
input
6 6
6 3
6 4
5 1
2 5
1 4
5 4
output
FHTAGN!
input
6 5
5 6
4 6
3 1
5 1
1 2
output
NO
Note

Let us denote as a simple cycle a set of v vertices that can be numbered so that the edges will only exist between vertices number 1 and22 and 3, ..., v - 1 and vv and 1.

A tree is a connected undirected graph consisting of n vertices and n - 1 edges (n > 0).

A rooted tree is a tree where one vertex is selected to be the root.


奈亚子只有一个环,环上每个点都是一棵树。。。

#include <iostream>
#include <cstring>

using namespace std;

int n,m;
int a[111][111];
int p[111]= {0};
int dis[111]= {0};
bool v[111]= {0};
int cnt=0;

bool find_cycle(int i,int papa)
{
    //cerr<<i<<" ------- "<<papa<<endl;
    v[i]=true;
    for (int j=1; j<=n; j++)
    {
        if (j!=papa&&i!=j&&a[i][j]>0)
        {
            if (!v[j])
            {
                p[cnt++]=j;
                if (find_cycle(j,i)) return true;
                cnt--;
            }
            else
            {
                p[cnt++]=j;
                return true;
            }
        }
    }
    return false;
}

bool dfs(int i,int papa)
{
    v[i]=true;
    for (int j=1;j<=n;j++)
    {
        if (i!=j&&j!=papa&&a[i][j])
        {
            if (papa==0&&dis[j]==0) continue;
            if (v[j]||dis[j]==0)
            {
                return true;
            }
            else
            {
                if (dfs(j,i)) return true;
            }
        }
    }
    return false;
}

void len_dfs(int i)
{
    v[i]=true;
    for (int j=1;j<=n;j++)
    {
        if (!v[j]&&a[i][j]>0) len_dfs(j);
    }
}

int main()
{
    memset(dis,-1,sizeof(dis));
    cin>>n>>m;
    for (int i=1; i<=m; i++)
    {
        int x,y;
        cin>>x>>y;
        a[x][y]=a[y][x]=1;
    }
    p[cnt++]=1;
    memset(v,0,sizeof(v));
    bool ret=find_cycle(1,0);
    if (ret)
    {
        dis[p[cnt-1]]=0;
        for (int i=cnt-2; i>=0; i--)
        {
            if (p[i]==p[cnt-1]) break;
            dis[p[i]]=0;
        }
        //ready_dfs
        for (int i=1;i<=n;i++)
        {
            if (dis[i]==0)
            {
                memset(v,0,sizeof(v));
                if (dfs(i,0))
                {
                    ret=false;
                    break;
                }
            }
        }
        //dfs_over
    }

    memset(v,0,sizeof(v));
    len_dfs(1);
    for (int i=1;i<=n;i++)
    {
        if (!v[i]) ret=false;
    }
    if (ret) cout<<"FHTAGN!"<<endl;
    else cout<<"NO"<<endl;

    return 0;
}




### Codeforces Div.2 比赛难度介绍 Codeforces Div.2 比赛主要面向的是具有基础编程技能到中级水平的选手。这类比赛通常吸引了大量来自全球不同背景的参赛者,包括大学生、高中生以及一些专业人士。 #### 参加资格 为了参加 Div.2 比赛,选手的评级应不超过 2099 分[^1]。这意味着该级别的竞赛适合那些已经掌握了一定算法知识并能熟练运用至少一种编程语言的人群参与挑战。 #### 题目设置 每场 Div.2 比赛一般会提供五至七道题目,在某些特殊情况下可能会更多或更少。这些题目按照预计解决难度递增排列: - **简单题(A, B 类型)**: 主要测试基本的数据结构操作和常见算法的应用能力;例如数组处理、字符串匹配等。 - **中等偏难题(C, D 类型)**: 开始涉及较为复杂的逻辑推理能力和特定领域内的高级技巧;比如图论中的最短路径计算或是动态规划入门应用实例。 - **高难度题(E及以上类型)**: 对于这些问题,则更加侧重考察深入理解复杂概念的能力,并能够灵活组合多种方法来解决问题;这往往需要较强的创造力与丰富的实践经验支持。 对于新手来说,建议先专注于理解和练习前几类较容易的问题,随着经验积累和技术提升再逐步尝试更高层次的任务。 ```cpp // 示例代码展示如何判断一个数是否为偶数 #include <iostream> using namespace std; bool is_even(int num){ return num % 2 == 0; } int main(){ int number = 4; // 测试数据 if(is_even(number)){ cout << "The given number is even."; }else{ cout << "The given number is odd."; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值