hiho一下 第215周 Circle Detect DFS有向图判环

hiho一下 第215周 Circle Detect

dfs判断有向环

比较常用的做法是DFS,同时在DFS过程中对点染色:

  1. 还没被DFS访问的点是白色的,初始时所有点都是白色的
  2. 如果点u已经被DFS访问过,但是u的子节点还未全部被访问到,那么把u染成灰色
  3. 如果点u以及u的子节点都被访问过了,从u回溯到u的父节点时,将u染成黑色

如果在DFS的过程中我们沿着有向边到达了一个灰色节点,则说明图中有环;如果从未到达过灰色节点,说明没有环。

set<int> st 储存头节点标号 ,建图使用链式前向星存边 , cor储存点的颜色

对所有头节点进行dfs遍历,并记录所遍历点的数目cnt

若在某次遍历中找到环则YES ,否则检查是否所有点都被遍历cnt<n?(头节点无法找到的环)

#include<stdio.h>
#include<string.h>
#include<set>
#include<algorithm>
using namespace std;
const int MAX=1e5+5;
struct Edge
{
    int to,nxt;
    Edge(){}
    Edge(int u,int v){to=u;nxt=v;}
    Edge(Edge &x){to=x.to;nxt=x.nxt;}
}e[MAX];
int head[MAX],cor[MAX],tot,n,m,cnt,ans;
set<int>st;
set<int>::iterator p;
void init()
{
    st.clear();
    for(int i=1;i<=n;i++) st.insert(i);
    memset(head,-1,sizeof(head));
    memset(cor,0,sizeof(cor));
    tot=0;cnt=0;ans=0;
}
void add(int u,int v)
{
    e[tot]=Edge(v,head[u]);
    head[u]=tot++;
    st.erase(v);
}
bool dfs(int u)
{
    ++cnt;
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(!cor[v]) {cor[v]=-1;bool f=dfs(v);if(f)return 1;}
        else if(cor[v]==-1) return 1;
    }
    cor[u]=1;
    return 0;
}
int main()
{
    int t,x,y;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        while(m--)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(p=st.begin();p!=st.end();++p)
            if(dfs(*p)){ans=1;break;}
        if(!ans&&cnt<n) ans=1;
        printf("%s\n",ans?"YES":"NO");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值