这个是判断有向图是否存在环的板子: (比较重要, 很多有向图的题中都要用)
int vis[maxn];
vector<int>g[maxn];
bool cycle(int u) { // 有环返回true, 否则返回false.
if (vis[u] == 1) return true;
if (vis[u] == 2) return false;
vis[u] = 1;
for (auto to : g[u]) {
if (cycle(to)) return true;
}
vis[u] = 2;
return false;
}
void solve()
{
int n, m;
cin >> n >> m;
for (int i = 1 ; i <= m ; i ++) {
int u, v;
cin >> u >> v;
g[u].pb(v); // 存图.
}
for (int i = 1 ; i <= n ; i ++) {
if (!vis[i] && cycle(i)) {
cout << -1 << endl;
return ;
}
}
}
判断无向图是否有环: (存个邻接表的..)
(这个就要讨论下了, 那就是两点之间有无重边了… 所以我们还是用万能的, 即标记边的编号而不是父亲节点了.)
忽略上面那句话, 因为这个和边双有点不同, 我们只是单纯的判环, 并用了一个标记数组, 所以直接递归处理就好, 遇到标记过的点就是有环即可, 重边不会影响的, 因为会多次访问那个点, 还是会导致return false的.
const int maxn = 1e5+5;
struct node {
int to, next;
}e[maxn<<1];
int vis[maxn];
int cnt, head[maxn];
void init() {
cnt = 0; Fill(head, -1);
}
void add(int u, int v) {
e[cnt] = node{v, head[u]};
head[u] = cnt++;
}
bool cycle(int u, int fa) {
if (vis[u]) return true;
vis[u] = 1;
for (int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if (to == fa) continue;
if (cycle(to, u)) return true;
}
return false;
}
void solve()
{
int n, m;
while(cin >> n >> m) {
init(); Fill(vis, 0);
for (int i = 1 ; i <= m ; i ++) {
int u, v;
cin >> u >> v;
add(u, v); add(v, u);
}
int f = 0;
for (int i = 1 ; i <= n ; i ++) {
if (!vis[i] && cycle(i, -1)) {
cout << "YES" << endl;
f = 1;
break ;
}
}
if (!f) cout << "NO" << endl;
}
}