zoukankan      html  css  js  c++  java
  • Bzoj4242:水壶

    Sol

    暴力就是每个建筑物跑一遍 (BFS) 然后最短距离建最小生成树,询问倍增
    正解比较巧妙
    每个点记录一个 (dis) 表示这个点到最近建筑的距离,(vis) 表示最近的是哪一个
    当一个建筑物走到它时,如果有其它的走到了这个点,那么直接两个建筑物连边

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    
    IL int Input(){
    	RG int x = 0, z = 1; RG char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	return x * z;
    }
    
    const int maxn(2005);
    const int maxm(4000005);
    const int maxp(2e5 + 5);
    
    struct Data{
    	int x, y;
    };
    
    struct Edge{
    	int v, w;
    };
    
    int k, n, m, vis[maxm], dis[maxm], qry, deep[maxp];
    int fa[maxp], idx, posx[maxm], posy[maxm], st[19][maxp], mx[19][maxp];
    int dx[4] = {0, 0, -1, 1}, dy[4] = {-1, 1};
    bool wall[maxm];
    char s[maxn];
    vector <Edge> graph[maxp];
    vector <Data> edge[maxm];
    queue <int> q;
    
    IL int Find(RG int x){
    	return x == fa[x] ? x : fa[x] = Find(fa[x]);
    }
    
    IL void Add(RG int u, RG int v, RG int w){
    	graph[u].push_back((Edge){v, w});
    	graph[v].push_back((Edge){u, w});
    }
    
    IL void Dfs(RG int u, RG int ff){
    	for(RG int i = 1; i <= 18; ++i){
    		st[i][u] = st[i - 1][st[i - 1][u]];
    		mx[i][u] = max(mx[i - 1][u], mx[i - 1][st[i - 1][u]]);
    	}
    	for(RG auto x: graph[u])
    		if(x.v != ff){
    			mx[0][x.v] = x.w, st[0][x.v] = u;
    			deep[x.v] = deep[u] + 1;
    			Dfs(x.v, u);
    		}
    }
    
    # define ID(i, j) ((i - 1) * m + j)
    
    IL int Calc(RG int u, RG int v){
    	RG int ret = 0;
    	if(deep[u] < deep[v]) swap(u, v);
    	for(RG int j = 18; ~j; --j)
    		if(deep[st[j][u]] >= deep[v]){
    			ret = max(ret, mx[j][u]);
    			u = st[j][u];
    		}
    	if(u == v) return ret;
    	for(RG int j = 18; ~j; --j)
    		if(st[j][u] != st[j][v]){
    			ret = max(ret, max(mx[j][u], mx[j][v]));
    			u = st[j][u], v = st[j][v];
    		}
    	return max(ret, max(mx[0][u], mx[0][v]));
    }
    
    int main(){
    	n = Input(), m = Input(), k = Input(), qry = Input();
    	for(RG int i = 1; i <= n; ++i){
    		scanf(" %s", s + 1);
    		for(RG int j = 1; j <= m; ++j){
    			++idx, posx[idx] = i, posy[idx] = j;
    			wall[idx] = s[j] == '#';
    		}
    	}
    	for(RG int i = 1; i <= k; ++i){
    		RG int px = Input(), py = Input(), id = ID(px, py);
    		vis[id] = fa[i] = i, dis[id] = 0, q.push(id);
    	}
    	while(!q.empty()){
    		RG int u = q.front(); q.pop();
    		for(RG int i = 0; i < 4; ++i){
    			RG int xx = posx[u] + dx[i], yy = posy[u] + dy[i];
    			if(xx < 1 || yy < 1 || xx > n || yy > m) continue;
    			RG int id = ID(xx, yy);
    			if(wall[id]) continue;
    			if(!vis[id]){
    				vis[id] = vis[u], dis[id] = dis[u] + 1;
    				q.push(id);
    			}
    			else edge[dis[id] + dis[u]].push_back((Data){vis[u], vis[id]});
    		}
    	}
    	for(RG int i = 0; i <= n * m; ++i)
    		for(RG auto v: edge[i]){
    			RG int fx = Find(v.x), fy = Find(v.y);
    			if(fx != fy) fa[fx] = fy, Add(v.x, v.y, i);
    		}
    	for(RG int i = 1; i <= k; ++i) if(!st[0][i]) Dfs(i, 0);
    	while(qry--){
    		RG int u = Input(), v = Input();
    		if(Find(u) != Find(v)) puts("-1");
    		else printf("%d
    ", Calc(u, v));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    MVC 网页制作
    Mvc 中国直辖市下拉列表(三级联动)
    MVC 登陆注册页面
    MVC 数据库增删改查(Razor)视图(2)
    MVC 数据库增删改查(Razor)方法(1)和数据库
    winform网页抓取邮箱单发群发并有附件
    winform截取网页邮箱
    winform 图标表chart
    winform图片读取存储于数据库SQL
    winform计算器
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/9171259.html
Copyright © 2011-2022 走看看