题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6165
题意:给出一个有向无自环,无重边的图,判断任意两点是否能到达(只要一个能抵达另一个即可)
这是做的第一道拓扑排序的题目,讲解可见:https://blog.csdn.net/qq_41713256/article/details/80805338
分析:因为只要求两点中任一点可到达另一点,也就是只要求是弱连通图。首先强连通分量内部肯定是可以是任意到达的,我们先利用Tarjan进行缩点形成一个有向无环图(DAG),在这个基础上我们进行拓扑排序,只要存在一条路径连接所有点的话,那么肯定是可以到达了,基于此我们在拓扑排序时,如果每一层都只有一个点入度为0 ,就可以得到唯一的一条路径连接所有点了,也就是说这时候就可以到达了。
#include<bits/stdc++.h>
#define maxn 1011
using namespace std;
vector<int>G[maxn],new_G[maxn];
stack<int>s;
int n,m;
int dfn[maxn],vis[maxn],low[maxn],color[maxn],colornum,cnt,in[maxn];
//in数组记录入度
bool toposort(int n){
queue<int>q;
int res=0;
for(int i=1;i<=n;i++) //n 节点的总数
if(in[i]==0) q.push(i),res++; //将入度为0的点入队列
if(res>1) return 0;
vector<int>ans; //ans 为拓扑序列,这个题目里没用到
while(!q.empty())
{ //cout<<233<<endl;
int p=q.front(); q.pop(); // 选一个入度为0的点,出队列
//cout<<p<<endl;
ans.push_back(p);
res=0;
for(int i=0;i<new_G[p].size();i++)
{
int y=new_G[p][i];
//if(p==2)cout<<G[p][i]<<endl;
in[y]--;
if(in[y]==0)
q.push(y),res++;
//cout<<p<<" "<<y<<endl;
}
if(res>1) return 0;
}
return 1;
}
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
s.push(x);
vis[x]=true;
for(int i=0;i<G[x].size();i++)
{
int q=G[x][i];
if (!dfn[q])
{
tarjan(q);
low[x]=min(low[x],low[q]);
}
else if (vis[q]) low[x]=min(low[x],dfn[q]);
}
if (low[x]==dfn[x])
{
colornum++;
int t;
do{
t=s.top();s.pop();
color[t]=colornum;
vis[t]=false;
}while(t!=x);
}
}
void init(int n){
colornum=0,cnt=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(color,0,sizeof(color));
memset(in,0,sizeof(in));
for(int i=1;i<=n;i++) G[i].clear();
}
int main(){
int T;scanf("%d",&T);
while(T--){
int n,m;scanf("%d%d",&n,&m);
init(n);//初始化
for(int i=1;i<=m;i++){
int x,y;scanf("%d%d",&x,&y);
G[x].push_back(y);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=colornum;i++){//对新建的图初始化
new_G[i].clear();
}
for(int i=1;i<=n;i++){
for(int j=0;j<G[i].size();j++){
if(color[i]!=color[G[i][j]]) in[color[G[i][j]]]++,new_G[color[i]].push_back(color[G[i][j]]);
}
}
//cout<<endl<<colornum<<endl;
if(toposort(colornum)){
printf("I love you my love and our love save us!\n");
}
else printf("Light my fire!\n");
}
return 0;
}