题意:一个有向图,问最多删去一条边后,是否能不存在环。
tags:找出一个环,然后环上每条边假设删去一次,每次判一下是否还有环。 O(n*m)
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 505, M = 100005; int n, m, vis2[M], head[N], tot; int cycle[N], cnt; bool vis[N]; struct Edge { int to, next; } e[M]; void Addedge(int u, int v) { e[tot]=(Edge){ v, head[u] }; head[u]=tot++; } void Init() { mes(head, -1); } int ti; bool dfs(int u) { vis[u] = true; cycle[++cnt] = u; for(int i=head[u], to; ~i, to=e[i].to; i=e[i].next) { if(to==ti) return true; if(!vis[to] && dfs(to)) return true; } --cnt; return false; } map< pair<int , int > , int > mp; queue< int > vec; int in[N], in2[N]; bool Toposort() { int u; while(!vec.empty()) { u = vec.front(); vec.pop(); for(int i=head[u], to, id; ~i, to=e[i].to, id=mp[MP(u,to)]; i=e[i].next) if(vis2[id]==0) { vis2[id]=1; --in[to]; if(in[to]==0) vec.push(to); } } rep(i,1,m) if(vis2[i]==0) return false; return true; } int main() { scanf("%d%d", &n, &m); Init(); int u, v; rep(i,1,m) { scanf("%d%d", &u, &v); Addedge(u, v); mp[MP(u, v)] = i; ++in2[v]; } rep(i,1,n) { mes(vis, false); ti = i; if(dfs(i)) break; cnt = 0; } if(cnt==0) return 0*printf("YES "); cycle[++cnt] = ti; rep(i,1,cnt-1) { mes(vis2, 0); vis2[ mp[MP(cycle[i],cycle[i+1])] ] = -1; --in2[cycle[i+1]]; rep(i,1,n) { if(in2[i]==0) vec.push(i); in[i] = in2[i]; } if(Toposort()) return 0*printf("YES "); ++in2[cycle[i+1]]; } puts("NO"); return 0; }