zoukankan      html  css  js  c++  java
  • 【BFS】【并查集】【Tarjan】【LCA】Gym

    给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子。

    把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队)。然后从大到小排序。然后用并查集将相邻(四联通)的点依次链接起来,如果不路径压缩的话,那么两个节点的LCA的所能容纳的箱子大小就是答案。于是用并查集辅助建树,之后离线询问,然后Tarjan跑个LCA即可。

    O(n^2+qlog(n)),log是因为map记录答案。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    vector<int>ask[1010*1010];
    int dx[]={0,1,0,-1,1,1,-1,-1},dy[]={1,0,-1,0,1,-1,1,-1};
    int e,v[1010*1010],first[1010*1010],next[1010*1010];
    void AddEdge(int U,int V){
    	v[++e]=V;
    	next[e]=first[U];
    	first[U]=e;
    }
    struct Point{
    	int x,y;
    	Point(const int &x,const int &y){
    		this->x=x;
    		this->y=y;
    	}
    	Point(){}
    };
    bool operator < (const Point &a,const Point &b){
    	return a.x!=b.x ? a.x<b.x : a.y<b.y;
    }
    map<Point,int>anss;
    struct Node{
    	Point p;
    	int d;
    	Node(const Point &p,const int &d){
    		this->p=p;
    		this->d=d;
    	}
    };
    int n,siz[1010][1010],Siz[1010*1010],m,K;
    int id[1010][1010];
    bool cmp(const Point &a,const Point &b){
    	return siz[a.x][a.y]>siz[b.x][b.y];
    }
    char a[1010][1010];
    queue<Node>q;
    bool vis[1010][1010];
    Point ps[1010*1010];
    int fa[1010*1010];
    int find(int x){
    	return x==fa[x] ? x : fa[x]=find(fa[x]);
    }
    Point qa[300010],qb[300010];
    bool not_rt[1010*1010];
    int ans[1010*1010];
    bool VIS[1010*1010];
    void LCA(int u)
    {
    	ans[u]=u;
    	for(int i=first[u];i;i=next[i])
    	  {
    	  	LCA(v[i]);
    	  	int f1=find(u),f2=find(v[i]);
    	  	fa[f1]=f2;
            ans[find(u)]=u;
    	  }
    	VIS[u]=true;
    	for(int i=0;i<ask[u].size();i++)
    	  if(VIS[ask[u][i]]){
    //	  	printf("%d %d %d %d
    ",min(u,ask[u][i]),max(u,ask[u][i]),ans[find(ask[u][i])],Siz[ans[find(ask[u][i])]]);
    		anss[Point(min(u,ask[u][i]),max(u,ask[u][i]))]=Siz[ans[find(ask[u][i])]];
    	  }
    }
    bool sb_q[300010];
    int main(){
    //	freopen("h.in","r",stdin);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%s",a[i]+1);
    	}
    	for(int i=0;i<=n+1;++i){
    		q.push(Node(Point(i,0),0));
    		vis[i][0]=1;
    		q.push(Node(Point(i,n+1),0));
    		vis[i][n+1]=1;
    	}
    	for(int i=0;i<=n+1;++i){
    		q.push(Node(Point(0,i),0));
    		vis[0][i]=1;
    		q.push(Node(Point(n+1,i),0));
    		vis[n+1][i]=1;
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			if(a[i][j]=='#'){
    				q.push(Node(Point(i,j),0));
    				vis[i][j]=1;
    			}
    		}
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			id[i][j]=++m;
    		}
    	}
    	m=0;
    	while(!q.empty()){
    		Node U=q.front(); q.pop();
    		int x=U.p.x,y=U.p.y;
    		for(int i=0;i<8;++i){
    			int tx=x+dx[i],ty=y+dy[i];
    			if(tx>=1 && tx<=n && ty>=1 && ty<=n && !vis[tx][ty]){
    				q.push(Node(Point(tx,ty),U.d+1));
    				siz[tx][ty]=Siz[id[tx][ty]]=2*U.d+1;
    				vis[tx][ty]=1;
    			}
    		}
    	}
    //	for(int i=1;i<=n;++i){
    //		for(int j=1;j<=n;++j){
    //			printf("%d ",siz[i][j]);
    //		}
    //		puts("");
    //	}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			if(siz[i][j]){
    				ps[++m]=Point(i,j);
    			}
    		}
    	}
    	for(int i=1;i<=m;++i){
    		fa[id[ps[i].x][ps[i].y]]=id[ps[i].x][ps[i].y];
    	}
    	sort(ps+1,ps+m+1,cmp);
    	memset(vis,0,sizeof(vis));
    	for(int i=1;i<=m;++i){
    		int x=ps[i].x,y=ps[i].y;
    		for(int j=0;j<4;++j){
    			int tx=x+dx[j],ty=y+dy[j];
    			if(a[tx][ty]=='.' && vis[tx][ty]){
    				int rt=find(id[tx][ty]);
    				if(rt!=find(id[x][y])){
    					AddEdge(id[x][y],rt);
    //					printf("%d %d
    ",id[x][y],rt);
    					not_rt[rt]=1;
    					fa[rt]=id[x][y];
    				}
    			}
    		}
    		vis[x][y]=1;
    	}
    	scanf("%d",&K);
    	for(int i=1;i<=K;++i){
    		scanf("%d%d%d%d",&qa[i].x,&qa[i].y,&qb[i].x,&qb[i].y);
    		int f1=find(id[qa[i].x][qa[i].y]),f2=find(id[qb[i].x][qb[i].y]);
    		if(f1==f2){
    			ask[id[qa[i].x][qa[i].y]].push_back(id[qb[i].x][qb[i].y]);
    			ask[id[qb[i].x][qb[i].y]].push_back(id[qa[i].x][qa[i].y]);
    		}
    		else{
    			sb_q[i]=1;
    		}
    	}
    	for(int i=1;i<=m;++i){
    		fa[id[ps[i].x][ps[i].y]]=id[ps[i].x][ps[i].y];
    	}
    	for(int i=1;i<=m;++i){
    		if(!not_rt[id[ps[i].x][ps[i].y]]){
    			LCA(id[ps[i].x][ps[i].y]);
    		}
    	}
    	for(int i=1;i<=K;++i){
    		if(sb_q[i]){
    			puts("0");
    		}
    		else{
    			printf("%d
    ",anss[Point(min(id[qa[i].x][qa[i].y],id[qb[i].x][qb[i].y]),
    			max(id[qa[i].x][qa[i].y],id[qb[i].x][qb[i].y]))]);
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    设计模式(23)>解释器模式 小强斋
    设计模式(21)>享元模式 小强斋
    访问者模式与双分派 小强斋
    将BMP格式的灰度图像或24位真彩图像二值化
    如何使用自定义Title
    ACM. Digital Roots
    jpegEncode
    ACM.Ones
    剩余定理
    ACM.DNA Sorting
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7214356.html
Copyright © 2011-2022 走看看