[CF915D] Almost Acyclic Graph

前言

重新认识拓扑排序

题目

洛谷

CF

讲解

首先我们考虑暴力枚举删的边,然后跑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;
}
posted @ 2020-08-23 09:40  皮皮刘  阅读(123)  评论(0编辑  收藏  举报