很久很久以前的一天,一位美男子來到海邊,海上狂風大作。美男子希望在海中找到美人魚,但是很不幸他只找到了章魚怪。
然而,在世界的另一端,人們正在積極的收集怪物的行為信息,以便研制出強大的武器來對付章魚怪。由于地震的多發,以及惡劣的天氣,使得我們的衛星不能很好的定位怪物,從而不能很好的命中目標。第一次射擊的分析結果會反映在一張由n個點和m條邊組成的無向圖上。現在讓我們來確定這張圖是不是可以被認為是章魚怪。
為了簡單起見,我們假設章魚怪的形狀是這樣,他有一個球形的身體,然后有很多觸須連接在他的身上。可以表現為一張無向圖,在圖中可以被認為由三棵或者更多的樹(代表觸須)組成,這些樹的根在圖中處在一個環中(這個環代表球形身體)。
題目保證,在圖中沒有重復的邊,也沒有自環。
單組測試數據第一行給出兩個數,n表示圖中的點的個數,m表示圖中邊的數量。 (1≤ n≤100,0≤ m≤ n*(n-1)/2 )接下來m行給出邊的信息,每一行有兩上數x,y (1≤ x,y≤ n,x≠y)表示點x和點y之間有邊相連。每一對點最多有一條邊相連,點自身不會有邊到自己。Output共一行,如果給定的圖被認為是章魚怪則輸出"FHTAGN!"(沒有引號),否則輸出"NO"(沒有引號)。Input示例6 66 36 45 12 51 45 4Output示例FHTAGN!思路:
按照題目要求一步一步來,首先這圖中一定有且只有一個長度不小于3的環,所以需要dfs搜索找到環,并且將環中的節點保存下來。這里我是利用一個deep數組來儲存每個節點在dfs樹中的深度,一開始deep都初始化成0,第一個遍歷的根節點deep是1,然后子節點依次+1,當前節點的所有子節點都遞歸結束的時候,當前節點的deep值變回0,當到達一個新的節點并且新的節點deep值不為0的時候,說明這里存在一個環,而組成環的節點就是deep值在當前節點u已經由的deep[u]和又一次對其賦值的k+1之間。當找到一個環的時候,剩下的就是要判斷以環上的每個點遍歷下去是否是一棵樹,這里要注意,要先將環上的邊都刪掉,然后將環上的所有節點的訪問標記vis都設成true。這樣,當dfs過程中遇到了vis為true的情況,則說明存在另外的環,輸出“NO"。vis的另外的作用就是判斷圖是否連通。如果有節點的vis在判斷完環上所有節點之后還是false,那說明圖不連通。代碼:
#include <bits/stdc++.h>using namespace std;const int MAXN = 105;int n, m;bool G[MAXN][MAXN], vis[MAXN];int deep[MAXN];vector <int> cir;int l, r;bool cmp(const int x, const int y) { return deep[x] < deep[y];}bool dfs(int u, int PRe, int k) { deep[u] = k; vis[u] = true; for (int v = 1; v <= n; v++) { if (!G[u][v] || v == pre) continue; if (vis[v]) { l = deep[v]; r = k + 1; return true; } if (dfs(v, u, k + 1)) return true; } deep[u] = 0; return false;}int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); G[u][v] = G[v][u] = true; } if (!dfs(1, -1, 1)) { puts("NO"); return 0; } for (int i = 1; i <= n; i++) { if (deep[i] >= l && deep[i] <= r) { cir.push_back(i); // printf("%d ", i); } } if (cir.size() < 3) { puts("NO"); return 0; } sort(cir.begin(), cir.end(), cmp); int cnt = cir.size(); for (int i = 0; i < cnt - 1; i++) G[cir[i]][cir[i + 1]] = G[cir[i + 1]][cir[i]] = false; G[cir[0]][cir[cnt - 1]] = G[cir[cnt - 1]][cir[0]] = false; memset(deep, 0, sizeof(deep)); memset(vis, false, sizeof(vis)); for (int i = 0; i < cnt; i++) vis[cir[i]] = true; for (int i = 0; i < cnt; i++) { if (dfs(cir[i], -1, 1)) { puts("NO"); return 0; } } for (int i = 1; i <= n; i++) { if (!vis[i]) { puts("NO"); return 0; } } puts("FHTAGN!"); return 0;}
新聞熱點
疑難解答