题意:
给定无向图,n个点,m条边,判断图中是否存在三元环。(n <= 1e5, m <= 3e6)
思路:
计数三元环的复杂度是mlogm,在这里1s跑不过。尝试通过bitset记录每个点的连边状态,再通过任意相连两点进行 & 操作判断,内存会爆掉。
可以通过一次bfs,给遍历的到的每个点确定一个父亲节点,画图可知,三元环中任意一点作为父节点,都可以给其余两个点标上相同的父节点。然后遍历所有边,判断两个端点是否有共同的父亲,是则存在三元环,否则不存在。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int maxm = 3e6+5;
struct node {
int u, v, next;
} edge[maxm*2];
int no, head[maxn];
void init() {
no = 0;
memset(head, -1, sizeof head);
}
void add(int u, int v) {
edge[no].u = u;
edge[no].v = v;
edge[no].next = head[u];
head[u] = no++;
}
int fa[maxn];
queue<int> q;
void bfs() {
while(!q.empty()) q.pop();
memset(fa, -1, sizeof fa);
q.push(1);
while(!q.empty()) {
int u = q.front(); q.pop();
for(int k = head[u]; k+1; k = edge[k].next) {
int v = edge[k].v;
if(fa[v] != -1) {
continue;
}
fa[v] = u;
q.push(v);
}
}
}
int n, m;
int main() {
scanf("%d %d", &n, &m);
init();
for(int i = 1; i <= m; ++i) {
int u, v;
scanf("%d %d", &u, &v);
add(u, v); add(v, u);
}
bfs();
bool flag = false;
for(int i = 0; i < no; ++i) {
int u = edge[i].u, v = edge[i].v;
if(fa[u] == fa[v]) {
flag = true;
break;
}
}
if(flag) {
puts("1");
}
else {
puts("0");
}
return 0;
}
/*
4 5
1 2
1 3
2 4
3 4
1 4
*/
继续加油~