[bzoj1601]灌水(洛谷P1550)

[USACO08OCT]Watering Hole G

洛谷灌水区

传送门

DescriptionDescription

Farmer John已经决定把水灌到他的 n(1<=n<=300)n(1<=n<=300) 块农田,农田被数字1到n标记。把一块土

地进行灌水有两种方法,从其他农田引水,或者这块土地建造水库。 建造一个水库需要花费

wi(1<=wi<=100000)wi(1<=wi<=100000),连接两块土地需要花费Pi,j(1<=Pi,j<=100000,Pi,j=Pj,i,Pi,i=0)P_{i,j}(1<=P_{i,j}<=100000,P_{i,j}=P_{j,i},P_{i,i}=0). 计算Farmer John所需的最少代价。

Input

第一行:一个数 nn

第二行到第 n+1n+1 行:第 i+1i+1 行含有一个数 wiwi

n+2n+2 行到第 2n+12n+1 行:第 n+1+in+1+i 行有 nn 个被空格分开的数,第 jj 个数代表 Pi,jP_{i,j}

OutputOutput

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

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

思路

老规矩 ,先看数据 暴力显然

咋看像一个最小生成树呢

自建水库的费用不就是超级源点到每一个土地的费用吗???

链接的费用不就是每一条边吗

ACcodeAC code

KruskalKruskal

#include <bits/stdc++.h>
using namespace std;

int n, m, fa[1000001], countt, sum, a, b[100001];
struct edge
{
    int u, v, w;
} e[1000001];
bool comp(edge a, edge b)
{
    return a.w < b.w;
}
int get(int x)
{
    return fa[x] == x ? x : fa[x] = get(fa[x]);
}
bool merge(int x, int y)
{ //判断是否<尚未>连通
    x = get(x);
    y = get(y);
    if (x == y)
        return false;
    fa[y] = x;
    return true;
}
void Kruskal()
{
    for (int i = 1; i <= m; i++)
    {
        if (merge(e[i].u, e[i].v))
            countt++, sum += e[i].w;
        if (countt == n)
            return;
    }
}
signed main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> b[i], e[++m].u = i, e[m].v = n + 1, e[m].w = b[i];
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> a;
            if (a)
            {
                e[++m].u = i;
                e[m].v = j;
                e[m].w = a;
            }
        }
    }
    sort(e + 1, e + m + 1, comp);
    for (int i = 1; i <= n; i++)
        fa[i] = i;
    Kruskal();
    cout << sum;
    return 0;
}

PrimPrim

#include <bits/stdc++.h>
using namespace std;

#define init(array, x) memset(array, x, sizeof(array))
const int maxn = 1e5 + 99;
int n, m, ans, vis[maxn];
struct node
{
    int to, w;
    bool operator<(const node tmp) const
    {
        return tmp.w < w;
    }
};
vector<node> d[maxn];
priority_queue<node> q;
void Prim(int x)
{
    int tot = 0;
    ans = 0;
    q.push((node){x, 0});
    while (tot <= n && !q.empty())
    {
        node t = q.top();
        q.pop();
        int tmp = t.to;
        if (vis[tmp])
            continue;
        vis[tmp] = 1;
        ans += t.w;
        tot++;
        for (int i = 0; i < d[tmp].size(); i++)
        {
            int to = d[tmp][i].to, w = d[tmp][i].w;
            if (!vis[to])
                q.push(d[tmp][i]);
        }
    }
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int a;
        cin >> a;
        d[0].push_back((node){i, a});
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            int a;
            cin >> a;
            if (i != j)
            {
                d[i].push_back((node){j, a});
            }
        }
    }
    Prim(0);
    cout << ans << endl;
    return 0;
}
posted @ 2021-05-08 10:42  蒟蒻orz  阅读(8)  评论(0编辑  收藏  举报  来源