SenseTime Ace Coder Challenge 暨 商汤在线编程挑战赛-白色相簿

题意:

给定无向图,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
*/


继续加油~

猜你喜欢

转载自blog.csdn.net/yo_bc/article/details/79948905
ACE