题目分析:无向图找奇圈的问题。首先我们做tarjan求出点双连通块,每一个块中用黑白染色法得到最长的奇圈,然后这个奇圈中不参加游戏的小孩就是这个连通块上的点个数cnt - 最长奇圈的长度dp,然后累加到ans上。则最后如果n-ans>=k则说明可以举办party,否则不行。
需要注意的是,当一个连通块只有两个点时,这两个点中只有一个点属于该连通块,是算法的特性。
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
//#include <cmath>
using namespace std ;
typedef long long LL ;
#pragma comment ( linker , "/STACK:1024000000" )
#define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define rec( i , A , o ) for ( int i = A[o] ; i != o ; i = A[i] )
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 1005 ;
const int MAXE = 2000005 ;
struct Edge {
int v , n ;
Edge () {}
Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} ;
Edge E[MAXE] ;
int H[MAXN] , cntE ;
int dfn[MAXN] , low[MAXN] , dfs_clock ;
int color[MAXN] ;
int bcc[MAXN] , bcc_cnt ;
int S[MAXN] , top ;
int ans ;
int dp ;
int n , m , k ;
int G[MAXN][MAXN] ;
void clear () {
ans = 0 ;
top = 0 ;
cntE = 0 ;
bcc_cnt = 0 ;
dfs_clock = 0 ;
clr ( G , 0 ) ;
clr ( H , -1 ) ;
clr ( bcc , 0 ) ;
clr ( dfn , 0 ) ;
}
void addedge ( int u , int v ) {
E[cntE] = Edge ( v , H[u] ) ;
H[u] = cntE ++ ;
}
void dfs ( int u , int dep ) {
for ( int i = H[u] ; ~i ; i = E[i].n ) {
int v = E[i].v ;
if ( bcc[v] != bcc_cnt ) continue ;
if ( !color[v] ) {
color[v] = 3 - color[u] ;
dfs ( v , dep + 1 ) ;
}
if ( color[v] != 3 - color[u] ) dp = max ( dp , dep ) ;
}
}
void tarjan ( int u , int fa = 0 ) {
dfn[u] = low[u] = ++ dfs_clock ;
S[top ++] = u ;
for ( int i = H[u] ; ~i ; i = E[i].n ) {
int v = E[i].v ;
if ( v == fa ) continue ;
if ( !dfn[v] ) {
tarjan ( v ) ;
low[u] = min ( low[u] , low[v] ) ;
if ( low[v] >= dfn[u] ) {
++ bcc_cnt ;
int cnt = 0 ;
while ( 1 ) {
int x = S[-- top] ;
bcc[x] = bcc_cnt ;
color[x] = 0 ;
cnt ++ ;
if ( x == v ) break ;
}
cnt ++ ;
bcc[u] = bcc_cnt ;
color[u] = 1 ;
dp = 0 ;
dfs ( u , 1 ) ;
//printf ( "%d %d\n" , cnt , dp ) ;
if ( dp ) ans += cnt - dp ;
else if ( cnt == 2 ) ans += cnt - 1 ;
}
} else low[u] = min ( low[u] , dfn[v] ) ;
}
}
void solve () {
int u , v ;
clear () ;
scanf ( "%d%d%d" , &n , &m , &k ) ;
rep ( i , 0 , m ) {
scanf ( "%d%d" , &u , &v ) ;
G[u][v] = G[v][u] = 1 ;
}
For ( i , 1 , n ) For ( j , 1 , n ) if ( i != j && !G[i][j] ) {
//printf ( "%d %d\n" , i , j ) ;
addedge ( i , j ) ;
}
For ( i , 1 , n ) if ( !dfn[i] ) tarjan ( i ) ;
//printf ( "%d\n" , n - ans ) ;
if ( n - ans >= k ) printf ( "Let's Fire!\n" ) ;
else printf ( "What a Pity.\n" ) ;
}
int main () {
int T ;
scanf ( "%d" , &T ) ;
while ( T -- ) solve () ;
return 0 ;
}