微子危机——建造

来源:互联网 发布:试玩软件赚钱 编辑:程序博客网 时间:2024/05/16 10:01

背景 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 61 12 22 43 35 15 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
原创粉丝点击