hdu 5253(最小生成树)

题解:用kruskal算法,把每个点和右、下两个方向的点的边存起来,权值就是差值的绝对值,然后按升序排序,用并查集找到最小生成树。

#include 
#include 
#include 
#include 
using namespace std;
const int N = 1005;
int m, n, g[N][N], cnt, pa[1000005];
struct Edge {
    int u, v, w;
}e[4000005];
long long sum, num;

bool cmp(Edge a, Edge b) {
    return a.w < b.w;
}

int get_parent(int x) {
    return x == pa[x] ? x : pa[x] = get_parent(pa[x]);
}

int Union(int x, int y) {
    int px = get_parent(x);
    int py = get_parent(y);
    if (px != py) {
        pa[px] = py;
        return 1;
    }
    return 0;
}

int main() {
    int t, cas = 1;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        int temp = n * m;
        for (int i = 0; i < temp; i++)
            pa[i] = i;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                scanf("%d", &g[i][j]);
        cnt = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) {
                if (j + 1 < m) {
                    e[cnt].u = i * m + j;
                    e[cnt].v = i * m + j + 1;
                    e[cnt++].w = abs(g[i][j + 1] - g[i][j]);
                }
                if (i + 1 < n) {
                    e[cnt].u = i * m + j;
                    e[cnt].v = (i + 1) * m + j;
                    e[cnt++].w = abs(g[i + 1][j] - g[i][j]);
                }
    /*          if (j - 1 >= 0) {
                    e[cnt].u = i * m + j;
                    e[cnt].v = i * m + j - 1;
                    e[cnt++].w = abs(g[i][j - 1] - g[i][j]);
                    printf("%d %d %d\n", e[cnt - 1].u, e[cnt - 1].v, e[cnt - 1].w);
                }
                if (i - 1 >= 0) {
                    e[cnt].u = i * m + j;
                    e[cnt].v = (i - 1) * m + j;
                    e[cnt++].w = abs(g[i - 1][j] - g[i][j]);
                    printf("%d %d %d\n", e[cnt - 1].u, e[cnt - 1].v, e[cnt - 1].w);
                }*/
            }
        sort(e, e + cnt, cmp);
        sum = 0;
        for (int i = 0; i < cnt; i++)
            if (Union(e[i].u, e[i].v))
                sum += e[i].w;
        printf("Case #%d:\n%lld\n", cas++, sum);
    }
    return 0;
}

你可能感兴趣的:(ACM-图论)