zoukankan      html  css  js  c++  java
  • 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,这样需要遍历的点就只有 (2cdot 2^{frac l2} = sqrt n) 个点。


    代码如下,在期望情况下的时间复杂度为 (O(ksqrt 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
    ", 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;
    }
    
  • 相关阅读:
    大项目之网上书城(五)——主页(End)
    # 大项目之网上书城(四)——主页(下中)
    大项目之网上书城(三)——主页(中)
    大项目之网上书城(二)——主页(上)
    大项目之网上书城(一)——注册页面
    Mycat
    centos7 bash: netstat: 未找到命令
    docker 推送镜像到Harbor错误修改
    Jenkins插件下载镜像加速
    docker镜像加速器
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj5049.html
Copyright © 2011-2022 走看看