1. 程式人生 > 實用技巧 >CF915D Almost Acyclic Graph

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;
}