1. 程式人生 > >915D Almost Acyclic Graph 拓撲排序

915D Almost Acyclic Graph 拓撲排序

題目:

D. Almost Acyclic Graphtime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard output

You are given a directed graph consisting of n vertices and m edges (each edge is directed, so it can be traversed in only one direction). You are allowed to remove at most one edge from it.

Can you make this graph acyclic by removing at most one edge from it? A directed graph is called acyclic iff it doesn't contain any cycle (a non-empty path that starts and ends in the same vertex).

Input

The first line contains two integers n and m (2 ≤ n ≤ 5001 ≤ m ≤ min(n(n - 1), 100000)) — the number of vertices and the number of edges, respectively.

Then m lines follow. Each line contains two integers u and v denoting a directed edge going from vertex u to vertex v (1 ≤ u, v ≤ nu ≠ v). Each ordered pair (u, v) is listed at most once (there is at most one directed edge from u to v).

Output

If it is possible to make this graph acyclic by removing at most one edge, print YES

. Otherwise, print NO.

題意:給出一個有向圖,如果從中任意刪除至多一條邊。問是否可以最終使圖變為無環圖。

思路:我們知道拓撲排序來判斷是否有環,就是不斷刪除入度為0的點(刪除時只關注節點入度!),最終比較刪除次數和點的關係。

而本題由於至多刪除一條邊,而刪除一條邊引起的變化就是某一點的入度減一。於是我們可以列舉每個點入度減一的情況,然後跑拓撲排序判斷是否還有環的存在。

程式碼:

#include<bits/stdc++.h>
#define sd(x) scanf("%d",&x)
#define ss(x) scanf("%s",x)
#define sc(x) scanf("%c",&x)
#define sf(x) scanf("%f",&x)
#define slf(x) scanf("%lf",&x)
#define slld(x) scanf("%lld",&x)
#define me(x,b) memset(x,b,sizeof(x))
#define pd(d) printf("%d\n",d);
#define plld(d) printf("%lld\n",d);
#define eps 1.0E-8
// #define Reast1nPeace

typedef long long ll;

using namespace std;

const int maxn = 510;

int n,m;

vector<int> G[maxn];
int in1[maxn];
int in2[maxn];

bool topsort(){
	queue<int> q;
	for(int i = 1 ; i<=n ; i++){
		if(!in2[i])	q.push(i);
	}
	int sum = 0;
	while(!q.empty()){
		int now = q.front(); q.pop();
		sum++;
		for(int i = 0 ; i<G[now].size() ; i++){
			int to = G[now][i];
			in2[to]--;
			if(!in2[to])	q.push(to);
		}
	}
	return sum==n;
}

int main(){
#ifdef Reast1nPeace
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i = 1 ; i<=m ; i++){
		int u,v; cin>>u>>v;
		G[u].push_back(v);
		in1[v]++;
	} 
	
	topsort();
	memcpy(in2,in1,sizeof(in1));
	if(topsort()){
		cout<<"YES"<<endl;
	}
	else{
		bool flag = 0;
		for(int i = 1 ; i<=n ; i++){
			if(in1[i]){
				memcpy(in2,in1,sizeof(in1));
				in2[i]--;
				if(topsort()){
					flag = 1;
					break;
				}
			}
		}
		if(flag){
			cout<<"YES"<<endl;
		}
		else{
			cout<<"NO"<<endl;
		}
	}
	return 0;
}