条边的有向图(无自环、无重边,2 ≤ n ≤ 500, 1 ≤ m ≤ min(n(n - 1), 100000) ),问能否通过删除其中的某一条边,使得该图无环。
判断有向图是否存在环我们是有拓扑排序。如果存在环,拓扑排序肯定是无法正常完成的。
我们统计所有入度,之后遍历每一个点。将当前点的入度-1,之后拓扑排序检测。
我们不需要遍历每一条边,那样太浪费时间。因为拓扑排序它不关注哪一个边,它只是利用的每一个点的入度情况。所以说,我们不需要枚举边,只需要枚举点即可。
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<queue>
using namespace std;
int mp[1100][1100];
int rudu1[1100],rudu2[1100];
int flag,n,m;
int sta[1100];
void tuopu()
{
int cnt=0;
queue<int>que;
for(int i=1;i<=n;i++)
{
if(rudu2[i]==0)
{
que.push(i);
cnt++;
}
}
while(!que.empty())
{
int u=que.front();
que.pop();
for(int i=1;i<=n;i++)
{
if(mp[u][i])
{
rudu2[i]--;
if(rudu2[i]==0)
{
cnt++;
que.push(i);
}
}
}
}
if(cnt!=n)
{
flag=0;
}
else
{
flag=1;
}
}
int main()
{
cin>>n>>m;
flag=0;
memset(rudu1,0,sizeof(rudu1));
memset(mp,0,sizeof(mp));
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
mp[a][b]=1;
rudu1[b]++;
}
for(int i=1;i<=n;i++)
{
if(rudu1[i]!=0)
{
for(int j=1;j<=n;j++)
{
rudu2[j]=rudu1[j];
}
rudu2[i]--;
tuopu();
if(flag)
break;
}
}
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}