Luo Gu P2872 [[USACO07DEC] road construction Building Roads]

P2872

Portal

First of all

Topic summarize: Title seek to make the ranch are all Unicom we need to build long way.

Obviously, this board is a minimum spanning tree problem (recommended for beginners do).

Then I say about kruskal it.

Kruskal's algorithm is a method used to find the minimum spanning tree algorithm, published by Joseph Kruskal in 1956.

To solve the same problem as well as Prim's algorithm and Boruvka algorithm. Three algorithms are greedy algorithm application.

Boruvka places and different algorithms, the same is also valid when the edge weights Kruskal's algorithm on the diagram. ------- comes from Baidu Encyclopedia

First, the basic idea

kruskal utilizes a greedy idea, first row at each edge sequence in accordance with the right side, use and maintenance of each set of check points.

Kruskal run when the first two points are judged not in a collection inside, if it did not have to explain in even the side.

Then merge right side when recording, engaged in a counter records plus the number of edges.

We all know that if there is a map \ (n \) nodes, then the minimum \ (n-1 \) edges can do it this chart Unicom.

Then we can wait for the count of the counter to remember \ (n-1 \) time to stop executing (has been positive solutions).

Since then this \ (n-1 \) edges to FIG joined together, then clearly \ (n - m \) edges can be divided into m parts to FIG. (Good like duck) example:. P1195

Second, the code

for (int i = 1; i <= cnt; i++) {
        if (father(edge[i].x) != father(edge[i].y)) {//判断是不是在一个集合中
            f++;
            unionn(edge[i].x, edge[i].y);//合并
            ans += edge[i].dis;//记录总权值
        }
        if (f == m) break;//如果做完了,那就停下啊.
    }

This problem codes and ideas:

Because there are some side there is a beginning, and those side then we can start right there are assigned to 0, and then continue to run kruskal enough.

Because given the coordinates, it would first coordinate all saved up, and then put these coordinates in accordance with the Euclidean distance between the two sides to build or two.

Euclidean distance formula: \ (\ sqrt {((X_ {-x_. 1} {2}) * (X_ {-x_. 1} {2}) + (-y_ Y_ {{2}}. 1) * ( y_ {1} -y_ {2} ))} \)

#include <bits/stdc++.h>

#define N 1000010
#define M 2010

using namespace std;
int fath[M], n, m; bool b[M];
double px[M], py[M];
struct node {//结构体存边.
    int x, y;
    double dis;
}edge[N << 2];

int read() {
    int s = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

int father(int x) {
    if (x != fath[x]) fath[x] = father(fath[x]);//求是不是在一个集合里
    return fath[x];
}

void unionn(int x, int y) {
    int fx = father(x), fy = father(y);//合并两个集合
    fath[x] = fath[y];
}

bool cmp(node p, node q) {
    return p.dis < q.dis;//sort用品
}

int main() {
    n = read(), m = read();
    int z = n + m;//原本就有的
    for (int i = 1; i <= z; i++) fath[i] = i;
    int cnt = 0;
    for (int i = 1, x, y; i <= n; i++) {
        x = read(), y = read();
        px[i] = x, px[i] = y;//因为给出的是坐标,先把坐标存起来.
    }
    for (int i = 1; i <= n; i++) fath[i] = 1;
    for (int i = n + 1, x, y; i <= n + m; i++) {
        x = read(), y = read();
        px[i] = x, py[i] = y;
    }
    for (int i = 1; i <= n + m; i++) {
        for (int j = i + 1; j <= n + m; j++) {//开始存边
            cnt++;
            edge[cnt].x = i;
            edge[cnt].y = j;
            edge[cnt].dis = sqrt((px[i] - px[j]) * (px[i] - px[j]) + (py[i] - py[j]) * (py[i] - py[j]));
        }
    }
    sort(edge + 1, edge + cnt + 1, cmp);//给边排一下序
    int f = 0;
    double ans = 0;
    for (int i = 1; i <= cnt; i++) {//kruskal
        if (father(edge[i].x) != father(edge[i].y)) {
            f++;
            unionn(edge[i].x, edge[i].y);
            ans += edge[i].dis;
        }
        if (f == m) break;
    }
    printf("%.2lf", ans);
}

Guess you like

Origin www.cnblogs.com/zzz-hhh/p/11606183.html