UPC-连接格点

山再高,往上爬,总能登顶;
路再长,走下去,定能到达。

链接各点

题目描述

有一个M行N列的点阵,相邻两点可以相连。一条纵向的连线花费一个单位,一条横向的连线花费两个单位。某些点之间已经有连线了,试问至少还需要花费多少个单位才能使所有的点全部连通。

输入

第一行输入两个正整数m和n。
以下若干行每行四个正整数x1,y1,x2,y2,表示第x1行第y1列的点和第x2行第y2列的点已经有连线。输入保证|x1-x2|+|y1-y2|=1。

输出

输出使得连通所有点还需要的最小花费。

Sample Input

2 2
1 1 2 1

Sample Output

3

Hint

30%数据:n*m<=1000
100%数据:m,n<=1000

题解分析
首先用一张同台图描写思路
在这里插入图片描述
首先因为竖着连的价格最小,所以先竖着连如果这两个点不在一个树内,即根不相同那么就把这两个链接,如图所示。
走完竖向之后走横向,就像图像所示,如果发现这两个的根是一个,那么就不连接,如果不是就连接。

但是这个是二维的并查集怎么办呢,其实这和一维的没有区别,咱们只需要确定好坐标,有点哈希的意思 就可以了。
咱们可以这样编号,以此图为例
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
是不是一下子就知道怎么肥4了
好嘞,这样我们就可以AC了
AC时间到

PS注意不要数指针漂移也不要数组越界。
数组至少开到1001*1001吧

#include<unordered_map>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<utility>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#pragma warning(disable:4244)
#define PI 3.1415926536
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
inline ll read() {
    ll c = getchar(), Nig = 1, x = 0;
    while (!isdigit(c) && c != '-')c = getchar();
    if (c == '-')Nig = -1, c = getchar();
    while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
    return Nig * x;
}
inline void out(ll a)
{
    if (a < 0)putchar('-'), a = -a;
    if (a >= 10)out(a / 10);
    putchar(a % 10 + '0');
}
ll qpow(ll x, ll n, ll mod) {
    ll res = 1;
    while (n > 0) {
        if (n & 1)res = (res * x) % mod;
        x = (x * x) % mod; n >>= 1;
    }
    return res;
}
#define read read()
int fa[1010025];
int find(int x) {
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy)fa[fx] = fy;
}
int main()
{
    for (int i = 1; i < 1010025; i++)fa[i] = i;
    int x = read, y = read;
    int x1, x2, y1, y2;
    int tot = 0;
    int num1, num2;
    while (scanf("%d%d%d%d", &x1, &y1, &x2, &y2) != EOF)
    {
        num1 = (x1 - 1) * y + y1;
        num2 = (x2 - 1) * y + y2;
        merge(num1, num2);
    }
    for (int j = 1; j <= y; j++)
        for (int i = 1; i < x; i++)
        {
            num1 = (i - 1) * y + j;
            num2 = num1 + y;
            if (find(num1) != find(num2))
            {
                tot++;
                merge(num1, num2);
            }
        }
    for (int i = 1; i <= x; i++)
        for (int j = 1; j < y; j++)
        {
            num1 = (i - 1) * y + j;
            num2 = num1 + 1;
            if (find(num1) != find(num2))
            {
                tot += 2;
                merge(num1, num2);
            }
        }
    cout << tot << endl;
}

By-轮月

发布了32 篇原创文章 · 获赞 11 · 访问量 1178

猜你喜欢

转载自blog.csdn.net/qq_35339563/article/details/104907584
UPC
今日推荐