zoukankan      html  css  js  c++  java
  • USACO 2008 Watering hole Prim

    题目

    题目描述

    Farmer John has decided to bring water to his N (1 <= N <= 300) pastures which are conveniently numbered 1..N. He may bring water to a pasture either by building a well in that pasture or connecting the pasture via a pipe to another pasture which already has water.

    Digging a well in pasture i costs W_i (1 <= W_i <= 100,000).

    Connecting pastures i and j with a pipe costs P_ij (1 <= P_ij <= 100,000; P_ij = P_ji; P_ii=0).

    Determine the minimum amount Farmer John will have to pay to water all of his pastures.

    POINTS: 400

    农民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 需要为连通整个牧场的每一块田地所需要的钱数。

    输入输出格式

    输入格式:

    第1 行为一个整数n。

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

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

    输出格式:

    只有一行,为一个整数,表示所需要的钱数。

    输入输出样例

    输入样例#1:
    4
    5
    4
    4
    3
    0 2 2 2
    2 0 3 3
    2 3 0 4
    2 3 4 0
    输出样例#1:
    9 

    分析

    要将图中的所有点连接起来,求最小的花费,这是一道典型的最小生成树。但是这道最小生成树的最大难点在于本题多了一个“井”的问题。同时挖井也有一定的花费。如何处理这个井就是我们接下来要考虑的问题。

    其实我们有一个非常“投机取巧”的方法。我们把Farmer John牌地下天然矿泉水源也考虑作一个点。这个地下水源到其他点路径的权值就是挖井的费用。然后就是一个没有什么特殊操作的裸Prim了!

    (最喜欢这种在模板上稍加改动的题目了)

    程序

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int MAXN = 300 + 1, INF = 0x3F3F3F3F;
     4 int n, w, p, EdgeCount=  0, Head[MAXN];
     5 struct edge
     6 {
     7     int Next, Aim, Weight;
     8 }Edge[MAXN*MAXN];
     9 void insert(int u, int v, int w)
    10 {
    11     Edge[++EdgeCount] = (edge){Head[u], v, w};
    12     Head[u] = EdgeCount;
    13 }
    14 int Prim()
    15 {
    16     bool vis[MAXN];
    17     int MinLen, Count = 1, ans = 0, visited[MAXN];
    18     visited[Count] = 0;
    19     vis[0] = 1;
    20     for (int i = 1; i <= n; i++)
    21     {
    22         MinLen = INF;
    23         for (int j = 1; j <= Count; j++)
    24             for (int k = Head[visited[j]]; k; k = Edge[k].Next)
    25                 if (!vis[Edge[k].Aim] && Edge[k].Weight < MinLen)
    26                 {
    27                     MinLen = Edge[k].Weight;
    28                     p = Edge[k].Aim;
    29                 }
    30         vis[p] = 1;
    31         ans += MinLen;
    32         Count++;
    33         visited[Count] = p;
    34     }
    35     return ans;
    36 }
    37 int main()
    38 {
    39     //freopen("testdata.in","r",stdin);
    40     //freopen("data.out","w",stdout);
    41     memset(Head,0,sizeof(Head));
    42     cin >> n;
    43     for (int i = 1; i <= n; i++)
    44     {
    45         cin >> w;
    46         insert(0,i,w);
    47         insert(i,0,w);
    48     }
    49     for (int i = 1; i <= n ; i++)
    50         for (int j = 1; j <= n; j++)
    51         {
    52             cin >> p;
    53             if (i != j)
    54                 insert(i,j,p);
    55         }
    56     cout << Prim() << endl;
    57     return 0;
    58 }
  • 相关阅读:
    Vijos / 题库 / 输油管道问题
    军事机密(Secret.pas)
    1164 统计数字
    1142 奖学金 sort做法
    1487 大批整数排序
    1487 大批整数排序
    1545 最简单排序
    1470 数列处理
    1683 车厢重组
    spin.js无图片实现loading进度条,支持但非依赖jquery
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/8425730.html
Copyright © 2011-2022 走看看