NOJ 1301 Gopher Hole 并查集好题 n*n矩阵上打洞 不相连洞的个数

  • [1301] Gopher Hole

  • 时间限制: 1000 ms 内存限制: 65535 K
  • 问题描述
  • Death-Moon loves telling stories.
    Some days ago, he told us a funny story.


    Long long ago, there is a hamster who is so naughty. Now, he comes to a place likes a N * N square. so, he is so excited to drill holes underground.


  • 输入
  • Input until EOF.
    Fisrt input two integers N (3 <= N < 100) and M (0 < M <2000). N is the side of N * N ground, M is the number of operations.

    Then follow M lines.
    Each line is a command:

    Out x y : Hamster will get out at (x, y) from underground. So, place (x, y) will be a hole.
    P : Calculate out the number of the holes and output (Two holes are connected when they share an edge).
    If two holes are connected, it means it is one hole.
  • 输出
  • For each 'P' command, output the number of the holes. Maybe hamster will get out at the same place more than once.
  • 样例输入
  • 3 5
    Out 0 0
    P
    Out 1 0
    Out 2 2
    P
  • 样例输出
  • 1
    2
  • 提示
  • 来源
  • Hungar

    题意:

    死月最爱讲故事了,这次他讲了个很有趣的故事。
    很久很久以前,有一只地鼠,他很调皮,很喜欢打洞。
    这次他来到一块 N * N 的地域,然后开始打洞。
    当输入是Out的时候,表示他将在(x, y)打洞,
    当有两个洞是拥有公共的边时,那么这两个洞是连通的,也就是说是属于同一个洞的。
     问一共会有多少个洞
     
     
    那么,每挖一次洞,就使用一次并查集。
    #include<stdio.h>
    #include<string.h>
    int parent[111111],rank[111111];
    int map[111][111];
    int dir[4][2]={0,1,0,-1,1,0,-1,0};
    int find_root(int x)
    {
    	return parent[x]==x?x:(parent[x]=find_root(parent[x]));//路径压缩  这里不一样了 多了个赋值
    	//return x==parent[x]?x:find_root(parent[x]);
    }
    int main()
    {
    	int m,n,i,x,j,y,n1,n2,pos1,pos2;
    	char ss[100];
    	while(scanf("%d %d",&n,&m)!=EOF)
    	{
    		int ans=0;
    		memset(map,0,sizeof(map));
    		int mid=n*n+10;
    		for(i=0;i<mid;i++)
    		{
    			parent[i]=i;
    			rank[i]=1;
    		}
    		for(i=0;i<m;i++)
    		{
    			scanf("%s",ss);
    			if(ss[0]=='O')
    			{
    				scanf("%d %d",&x,&y);
    				if(map[x][y]==1) continue;//注意这里啊  防止重复在某个点挖洞 否则会产生重复计算
    				map[x][y]=1;
    				for(j=0;j<4;j++)
    				{
    					int xx=x+dir[j][0];
    					int yy=y+dir[j][1];
                        if(xx>=0&&xx<n&&yy>=0&&yy<n)
    					{
    						if(map[xx][yy]==0) continue;
    					          else break;
    					}
    				}
    				if(j==4)  {ans++; continue;}//如果这个洞 周围全不是洞 那么洞的数量加1
                    int p=1;//表示 x y点产生的一个洞
    				for(j=0;j<4;j++)
    				{
    					int xx=x+dir[j][0];
    					int yy=y+dir[j][1];
    					if(xx<0||xx>=n||yy<0||yy>=n||map[xx][yy]==0) continue;
    					pos1=x*n+y;
    					pos2=xx*n+yy;
    					n1=find_root(pos1);
    					n2=find_root(pos2);
    					if(n1!=n2)               
    					{     
    						p--;//如果合并了  说明少了一个洞 
    						if(rank[n1]>=rank[n2])        
    						{                         
    							parent[n2]=n1;             
    							rank[n1]+=rank[n2];          
    						}                    
    						else                
    						{                    
    							parent[n1]=n2;          
    							rank[n2]+=rank[n1];         
    						}   
    					}
    				}
    				ans+=p;
    			}
    			else 
    				printf("%d\n",ans);
    		}
    	}
    	return 0;
    }

     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值