洛谷 P1550 [USACO08OCT]打井Watering Hole

洛谷 P1550 [USACO08OCT]打井Watering Hole

Description

  • 农民John 决定将水引入到他的n(1<=n<=300)个牧场。他准备通过挖若

    干井,并在各块田中修筑水道来连通各块田地以供水。在第i 号田中挖一口井需要花费W_i(1<=W_i<=100,000)元。连接i 号田与j 号田需要P_ij (1 <= P_ij <= 100,000 , P_ji=P_ij)元。

    请求出农民John 需要为使所有农场都与有水的农场相连或拥有水井所需要的钱数。

Input

  • 第1 行为一个整数n。

    第2 到n+1 行每行一个整数,从上到下分别为W_1 到W_n。

    第n+2 到2n+1 行为一个矩阵,表示需要的经费(P_ij)。

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

题解:

  • 妙题。妙不可言。
  • 这题如果不建虚点写是很难写的,建了虚点你会恍然大悟
  • 对于一个农场自己打井,花费val的价钱,可以理解为它向地下的天然井水0号结点连一条权值为val的边
  • 所以就有了n + 1个点,跑一遍最小生成树就好了
#include <iostream>
#include <cstdio>
#include <algorithm>
#define maxm 100005
using namespace std;

struct E {int u, v, w;} e[maxm];
int n, cnt, ans, tot;
int fat[maxm];

bool cmp(E x, E y) {
    return x.w < y.w;
}

int getFat(int x)
{
    if(x == fat[x]) return x;
    else return fat[x] = getFat(fat[x]);
}

void minTree()
{
    for(int i = 1; i <= n; i++) fat[i] = i;
    sort(e + 1, e + 1 + cnt, cmp);
    for(int i = 1; i <= cnt; i++)
    {
        if(getFat(e[i].u) != getFat(e[i].v))
            fat[getFat(e[i].u)] = getFat(e[i].v),
            ans += e[i].w, tot++;
        if(tot == n - 1) break;
    }
}

int main()
{
    cin >> n;
    n++;
    for(int i = 2; i <= n; i++)
    {
        int w;  cin >> w;
        e[++cnt].u = i, e[cnt].v = 1, e[cnt].w = w;
    }
    for(int i = 2; i <= n; i++)
        for(int j = 2; j <= n; j++)
        {
            int w;  cin >> w;
            e[++cnt].u = i, e[cnt].v = j, e[cnt].w = w;
        }
    minTree();
    cout << ans;
    return 0;
}

转载于:https://www.cnblogs.com/BigYellowDog/p/11216298.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值