HDU 6165 FFF at Valentine

题目大意:给出一个有向图,问你这个图中是否对于任意两点\(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;
}

猜你喜欢

转载自www.cnblogs.com/cjjsb/p/9415829.html
fff