前言
重新认识拓扑排序
题目
讲解
首先我们考虑暴力枚举删的边,然后跑topu判环
时间复杂度(O(m^2)=O(TLE))
但是枚举每一条边真的有必要吗?
我们想到枚举一条边后无非就是让一个点的入度减一罢了
为什么不直接枚举让哪个点入度减一呢?
时间复杂度(O(nm)=O(AC))
代码
int head[MAXN],tot;
struct edge
{
int v,nxt;
}e[MAXM];
void Add_Edge(int x,int y)
{
e[++tot].v = y;
e[tot].nxt = head[x];
head[x] = tot;
}
int ru[MAXN],ru1[MAXN];
queue<int> q;
bool topu()
{
for(int i = 1;i <= n;++ i) ru[i] = ru1[i];
for(int i = 1;i <= n;++ i) if(!ru[i]) q.push(i);
int cnt = 0;
while(!q.empty())
{
int t = q.front();q.pop();
cnt++;
for(int i = head[t]; i ;i = e[i].nxt)
{
ru[e[i].v]--;
if(!ru[e[i].v])
q.push(e[i].v);
}
}
return cnt == n;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = Read(); m = Read();
for(int i = 1;i <= m;++ i)
{
int u = Read(),v = Read();
Add_Edge(u,v);ru1[v]++;
}
for(int i = 1;i <= n;++ i)
{
if(ru1[i])
{
ru1[i]--;
if(topu()) {printf("YES");return 0;}
ru1[i]++;
}
}
printf("NO");
return 0;
}