微子危机——建造

背景 Background
№.2
邪恶的Guiolk联盟采集好了微子能,就要运输。Guiolk联盟的领袖TT此时才发现,自己的军事基地中由微子发射器组成的微子能量网存在很大的问题,于是他决定修改。
描述 Description
之前,TT为了整齐,把军事基地建成了矩形,而且如果两个微子发射器的连线平行于军事基地的一边,这两个微子发射器之间就一定有微子能量传输线相连。
(*注:比如有3个微子发射器A(1,1)、B(1,3)、C(2,2),那么A和B之间有微子能量传输线相连,A和B不能传输到C。*)
但是在微子能运输过程中发现,常常不能从一个微子发射器运抵另一个微子发射器。
为了可以从任何一个微子传输器能运抵其它任意一个微子传输器,而且能和原来的微子能量网同样整齐,TT决定遵循原来的规则,调动他的百万农奴新修建一些微子能量传输线和微子发射器。由于微子发射器的造价比微子传输线高得多,所以TT决定忽略微子能量传输线的成本。
但是TT又不想花费不必要的钱,所以找到你为他计算最少需要建多少个微子发射器。
输入格式 InputFormat
第一行三个正整数n、m、p。(2<=n,m<=100000,表示军事基地的两边长;2<=p<=200000,表示微子发射器的个数。)
接下来p行,每行两个正整数数Xi、Yi(1<=Xi<=n  1<=Yi<=m),代表每个微子发射器在军事基地的位置。(可能会由于疏漏,有些微子发射器重复)
输出格式 OutputFormat
只有一行,为最少修建微子发射器的数量。
样例输入 SampleInput 
5 6 6
1 1
2 2
2 4
3 3
5 1
5 5
样例输出 SampleOutput 
2
数据范围和注释 Hint
样例的一种方案:
#.....
|#-#..
|.#+..
|.|...
#-+-#.

#表示原有微子发射器,-、|表示微子能量传输线,+表示兴建的微子发射器。所以至少兴建2个微子发射器。
如果看不清楚,请复制到记事本查看。
思路:
并查集应用。
#include <stdio.h>

int x[100001], y[100001], bcj[200002];       //x存x坐标对应的节点所在集合,y同理, bcj所有集合的并查集

int findfather(int x)
{
	if(bcj[x] == 0)
	{
		return x;
	}
	else
	{
		return findfather(bcj[x]);
	}
}

int merge(int sp, int ep)             //路径压缩(根节点改变时,改变所有以原根节点为根节点的节点, 以便压缩寻找根节点的的路径)
{
	int pre = sp, now;
	ep = findfather(ep);
	while(pre != 0)
	{
		now = pre;
		pre = bcj[now];
		if((pre == 0 && now != ep) || pre != 0)    //注意如果now==ep时,不能标记,否则就死循环了
		bcj[now] = ep;
	}
	return 0;
}

int main()
{
	int i, tx, ty, n, m, p, cnt, a, b, ans;
	cnt = 1;
	scanf("%d%d%d", &n, &m, &p);
	for(i = 0; i < p; i++)
	{
		scanf("%d%d", &tx, &ty);
		if(x[tx] == 0 && y[ty] == 0)
		{
			x[tx] = y[ty] = cnt;
			cnt++;
		}
		else if(x[tx] == 0 && y[ty] != 0)
		{
			x[tx] = y[ty];
		}
		else if(x[tx] != 0 && y[ty] == 0)
		{
			y[ty] = x[tx];
		}
		else
		{
			merge(x[tx], y[ty]);
		}
	}
	for(ans = 0, i = 1; i < cnt; i++)
	{
		if(bcj[i] == 0)
		{
			ans++;
		}
	}
	printf("%d\n", ans-1);
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值