题解:先找出所有的强连通分量,再判断各分量能否满足要求(方法:不断地除去入度为0的分量,若出现两个入度为0的分量则不合法)
#include<iostream>
#include<stdio.h>
#include<vector>
#include<stack>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1005;
int t,n,m,dfn[maxn],f[maxn],low[maxn],mp[maxn][maxn],in[maxn],q[maxn],c,index,cnt;
bool instack[maxn];
vector<int> e[maxn];
stack<int> s;
void tarjan(int u){
dfn[u]=low[u]=++index;
s.push(u);
instack[u]=1;
for(int i=0;i<e[u].size();i++){
int v=e[u][i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
cnt++;
int v;
do{
v=s.top();
s.pop();
instack[v]=0;
f[v]=cnt;
}while(v!=u);
}
}
void solve(){
int cur=0;
while(cur<c){
if(c-cur>1){
printf("Light my fire!\n");
return;
}
int u=q[cur++];
for(int i=1;i<=cnt;i++)
if(mp[u][i]){
in[i]--;
if(!in[i]) q[c++]=i;
}
}
printf("I love you my love and our love save us!\n");
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
index=cnt=c=0;
memset(mp,0,sizeof(mp));
for(int i=1;i<=n;i++) e[i].clear(),dfn[i]=low[i]=in[i]=0,instack[i]=0;
for(int u,v,i=0;i<m;i++){
scanf("%d%d",&u,&v);
e[u].push_back(v);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int u=1;u<=n;u++)
for(int i=0;i<e[u].size();i++){
int a=f[u],b=f[e[u][i]];
if(a==b||mp[a][b]) continue;
mp[a][b]=1;in[b]++;
}
for(int i=1;i<=cnt;i++) if(!in[i]) q[c++]=i;
solve();
}
}