【题目描述】
有一个M行N列的点阵,相邻两点可以相连。一条纵向的连线花费一个单位,一条横向的连线花费两个单位。某些点之间已经有连线了,试问至少还需要花费多少个单位才能使所有的点全部连通。
【输入】
第一行输入两个正整数m和n。
以下若干行每行四个正整数x1,y1,x2,y2x1,y1,x2,y2,表示第x1x1行第y1y1列的点和第x2x2行第y2y2列的点已经有连线。输入保证|x1−x2|+|y1−y2|=1|x1−x2|+|y1−y2|=1。
【输出】
输出使得连通所有点还需要的最小花费。
【输入样例】
2 2 1 1 2 1
【输出样例】
3
【提示】
【数据规模】
30%数据:n*m≤1000
100%数据:m,n≤1000
这题很有意思的一题,就是把坐标换成一个数,然后用并查集来做,这样就转换成我们平常做的类型,比较简单
还有一个问题,刚用vs不久,和我熟悉的codeblocks有点区别对于:ctrl+z在vs里是用ctrl+Y
ac代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e6+10;
int n, m;
int p[N];
int findth(int x)
{
if (x == p[x]) return x;
return p[x] = findth(p[x]);
}
int unionn(int x, int y)
{
int xx = findth(x);
int yy = findth(y);
if (xx != yy) {
p[yy] = xx;
return 1;
}
return 0;
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1;i <= n * m;i++) p[i] = i;
int x1, y1, x2, y2;
while (scanf("%d %d %d %d", &x1, &y1, &x2, &y2) == 4) {
unionn((x1 - 1)*m + y1, (x2 - 1)*m + y2);
}
int sum = 0;
for (int i = 1;i <= m;i++) {
for (int j = 1;j < n;j++) {
if (unionn((j - 1)*m + i, j*m + i))
sum++;
}
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j < m;j++) {
if (unionn((i - 1)*m + j, (i - 1)*m + j + 1) ) sum += 2;
}
}
printf("%d\n", sum);
return 0;
}