bzoj5049 [Lydsy1709月赛]导航系统 双向bfs

题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=5049

题解

题面里面满眼的随机。既然数据完全随机,那就是在锻炼选手的乱搞能力啊。

根据一个常用的结论,一棵随机的树的深度不超过 \(\log n\),大概等价于一个点期望下有 \(2\) 个孩子。

那么这个图中,以某个点为根的最短路树也应该满足。不妨设 \(dis(u,v) = l\),根据之前的结论,\(l \leq \log n\)。那么如果直接暴力 bfs 建最短路的话,需要遍历 \(2^l = n\) 个点。这样的情况可以使用双向 bfs,这样需要遍历的点就只有 \(2\cdot 2^{\frac l2} = \sqrt n\) 个点。


代码如下,在期望情况下的时间复杂度为 \(O(k\sqrt n)\)

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
	int f = 0, c;
	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
	x = c & 15;
	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
	f ? x = -x : 0;
}

const int N = 100000 + 7;
const int M = 300000 + 7;

int n, m, qq;
int fa[N], sz[N], q[N], vis[N], dis[N];

struct Edge { int to, ne; } g[M << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }

inline int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
inline void merge(int x, int y) {
	x = find(x), y = find(y);
	if (sz[x] < sz[y]) std::swap(x, y);
	fa[y] = x, smax(sz[x], sz[y] + 1);
}

inline int bfs(int s, int t) {
	int hd = 0, tl = 0;
	q[++tl] = s, vis[s] = 1, dis[s] = 0;
	q[++tl] = t, vis[t] = -1, dis[t] = 0;
	while (hd < tl) {
		int x = q[++hd];
		for fec(i, x, y) if (!vis[y]) dis[y] = dis[x] + 1, vis[y] = vis[x], q[++tl] = y;
		else if (vis[y] != vis[x]) {
			for (int i = 1; i <= tl; ++i) vis[q[i]] = 0;
			return dis[x] + dis[y] + 1;
		}
	}
	return -1;
}

inline void work() {
	while (qq--) {
		int x, y;
		read(x), read(y);
		if (find(x) != find(y)) puts("-1");
		else printf("%d\n", bfs(x, y));
	}
}

inline void init() {
	read(n), read(m), read(qq);
	int x, y;
	for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1;
	for (int i = 1; i <= m; ++i) read(x), read(y), adde(x, y), merge(x, y);
}

int main() {
#ifdef hzhkk
	freopen("hkk.in", "r", stdin);
#endif
	init();
	work();
	fclose(stdin), fclose(stdout);
	return 0;
}
posted @ 2019-09-20 09:51  hankeke303  阅读(173)  评论(0编辑  收藏  举报