题目大意:给出一个有向图,问你这个图中是否对于任意两点\(u,v\),都至少满足\(u\to v\)(\(u\)可到达\(v\),下同)或\(v\to u\)中的一个。
一看就是套路的图论题,我们先把边连起来。
考虑一个很基本的性质:在一个强连通分量的点两两可达
于是肯定先Tarjan缩一波点。然后我们得到了一个DAG
接下来就是考虑是否有两个点(当然是缩点之后的了)互不可达。
这个可以直接跑一边拓扑排序。然后看一下是否在某个时刻有两个点的入度为零即可。
CODE
#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;
const int N=1005;
struct edge
{
int to,next;
}e[N*6],ne[N*6];
int head[N],nhead[N],t,n,m,x,y,cnt,tot,sum,dfn[N],low[N],col[N],stack[N],ru[N],q[N],top;
bool vis[N];
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+ch-‘0‘,isdigit(ch=tc()));
}
inline void add(int x,int y)
{
e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
}
inline void nadd(int x,int y)
{
ne[++cnt].to=y; ne[cnt].next=nhead[x]; nhead[x]=cnt;
}
inline void clear(void)
{
memset(head,-1,sizeof(head)); memset(e,-1,sizeof(e));
memset(nhead,-1,sizeof(nhead)); memset(ne,-1,sizeof(ne));
memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis));
memset(col,0,sizeof(col)); memset(ru,0,sizeof(ru));
cnt=tot=sum=top=0;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
inline void Tarjan(int now)
{
dfn[now]=low[now]=++tot; vis[now]=1; stack[++top]=now;
for (register int i=head[now];i!=-1;i=e[i].next)
if (!dfn[e[i].to]) Tarjan(e[i].to),low[now]=min(low[now],low[e[i].to]);
else if (vis[e[i].to]) low[now]=min(low[now],dfn[e[i].to]);
if (dfn[now]==low[now])
{
vis[now]=0; col[now]=++sum;
while (now!=stack[top])
{
vis[stack[top]]=0; col[stack[top--]]=sum;
} --top;
}
}
inline bool top_sort(void)
{
register int i,H=0,T=0;
for (i=1;i<=sum;++i)
if (!ru[i]) q[++T]=i;
while (H<T)
{
if (T-H>1) return 0;
int now=q[++H];
for (i=nhead[now];i!=-1;i=ne[i].next)
if (!(--ru[ne[i].to])) q[++T]=ne[i].to;
}
return 1;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j; read(t);
while (t--)
{
clear(); read(n); read(m);
for (i=1;i<=m;++i)
read(x),read(y),add(x,y);
for (i=1;i<=n;++i)
if (!dfn[i]) Tarjan(i);
for (cnt=0,i=1;i<=n;++i)
for (j=head[i];j!=-1;j=e[j].next)
if (col[i]!=col[e[j].to]) nadd(col[i],col[e[j].to]),++ru[col[e[j].to]];
if (top_sort()) puts("I love you my love and our love save us!"); else puts("Light my fire!");
}
return 0;
}
原文地址:https://www.cnblogs.com/cjjsb/p/9415829.html
时间: 2024-10-12 12:28:30