[CF117C]Cycle

题目链接:

CF117C

Luogu Remote Judge

似乎这题\(DFS\)可过。。我就是饿死也不会用DFS

我们考虑最暴力的做法:枚举\(3\)个点判断是否形成环。

但是\(O(n^3)\)是肯定过不了的。

那么先枚举前\(2\)个点,就要判断第\(2\)个点出发有没有一个点和第\(1\)个点联通。

先预处理哪些点和第\(1\)个点联通,那么就是求第\(2\)个点能够到达的点集和能够到达第\(1\)个点的点集有没有交集。

这里用bitset优化即可。

时间复杂度 \(O(\frac{n^3}{32})\)

bitset要手写,\(STL\)的常数太大了。

代码:

#include <cstdio>
#include <cstring>
typedef unsigned long long ull;

struct Bitset
{
    ull a[80];

    inline void Set(const int x){a[x>>6]|=1ull<<(x&63);}//将第x位设为1

    inline bool Get(const int x){return a[x>>6]>>(x&63)&1;}//获取第x位的值

    inline bool Match(const Bitset &b)//判断和b是否有交集
    {
        for(int i=0;i<80;++i)
            if(a[i]&b.a[i])return true;
        return false;
    }

    inline void Clear(){memset(a,0,sizeof a);}//清空
};

int n;
char s[5005];
Bitset g[5005],a;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s+1);
        for(int j=1;j<=n;++j)
            if(s[j]&1)g[i].Set(j);
    }
    for(int i=1;i<=n;++i)
    {
        a.Clear();
        for(int j=1;j<=n;++j)
            if(g[j].Get(i))
                a.Set(j);
        for(int j=1;j<=n;++j)
            if(g[i].Get(j))
                if(g[j].Match(a))
                    for(int k=1;k<=n;++k)//有解,暴力找解。
                        if(g[j].Get(k)&&g[k].Get(i))
                            return printf("%d %d %d\n",i,j,k),0;
    }
    return puts("-1"),0;
}
posted @ 2019-02-15 16:54  LanrTabe  阅读(232)  评论(0编辑  收藏  举报