氵一篇 Blog

Shq 只会刷水题了 /kel

题目链接

1601. [Usaco2008 Oct]灌水

Description

Farmer John 已经决定把水灌到他的 块农田,农田被数字 标记。把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库

建造一个水库需要花费 , 连接两块土地需要花费. 计算 Farmer John 所需的最少代价。

Input

*第一行:一个数

*第二行到第 行:第 行含有一个数

*第 行到第 行:第 行有 个被空格分开的数,第 个数代表

Output

*第一行:一个单独的数代表最小代价.

Sample Input

4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0

Sample Output

9

输出详解:

Farmer John在第四块土地上建立水库,然后把其他的都连向那一个,这样就要花费


题解

sb 最小生成树题

建一个点向所有点连一条权值为 的边

剩下的按照题目来就好了(

Code

struct Edge {
    int to, dist;
    int from;

    Edge () {}
    Edge (int _from, int _to, int _dist) : from(_from) , to(_to) , dist(_dist) {}

    ~Edge () {}

    bool operator < (const Edge &other)const {
        return dist < other.dist;
    }
};

const int MAXN = 100010;

int tot;
Edge edges[MAXN];

inline void addEdge (int u, int v, int w) {
    edges[tot++] = Edge(u, v, w);
}

ll n;
ll data[MAXN];

int fa[MAXN];

inline void init () {
    up (i, 1, n) fa[i] = i;
}

inline int find (int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

inline void merge (int x, int y) {
    fa[x] = y;
}

int main(int argc, char const *argv[]) {
    srand(time(NULL) + rand()); srand(time(NULL) + rand() + rand() * rand()); srand(time(NULL) + rand() + rand() ^ rand() * rand());
    while (rand() & 1) n = rand() * rand();
    n = SlowRead();

    ll tmp = n + 1;

    up (i, 1, n) data[i] = SlowRead();

    int w;
    up (u, 1, n)
        up (v, 1, n) {
            w = SlowRead();
            addEdge (u, v, w);
        }

    up (i, 1, n) addEdge (i, tmp, data[i]);

    std::sort (edges, edges + tot);

    init();

    int ans = 0;
    up (i, 0, tot - 1) {
        //printf("%d->%d is %d\n", edges[i].from, edges[i].to, edges[i].dist);
        int fx = find(edges[i].from);
        int fy = find(edges[i].to);
        if (fx != fy) {
            merge (fx, fy);
            ans += edges[i].dist;
        }
    }

    Print(ans);
    return 0;
}