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 }

原文地址:https://www.cnblogs.com/OIerPrime/p/8425730.html

时间: 2024-10-18 00:38:43

USACO 2008 Watering hole Prim的相关文章

usaco oct09 Watering Hole

Farmer John希望把水源引入他的N (1 <= N <= 300) 个牧场,牧场的编号是1~N.他将水源引入某个牧场的方法有两个,一个是在牧场中打一口井,另一个是将这个牧场与另一个已经有水源的牧场用一根管道相连.在牧场i中打井的费用是W_i (1 <= W_i <= 100000).把牧场i和j用一根管道相连的费用是P_ij (1 <= P_ij <= 100000, P_ij = P_ji, P_ii = 0).请你求出Farmer John最少要花多少钱才能

P1550 [USACO08OCT]打井Watering Hole

P1550 [USACO08OCT]打井Watering Hole 题目比较简单,却提醒了图论建图的的重要性. 很多时候建图不只是要将给定的信息建立,还需要添加辅助点. 不过这题是真水 #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using std::sort; const int maxn=500; struct node { int A,B; int

【BZOJ1229】【USACO 2008 Nov Gold】 4.Toys sadstory 三分+贪心

sad story:我们自己oj的数据貌似有点问题.标程WA了5% 题解: 复制去Google翻译翻译结果 首先引一下VFK神犇的证明来证明一下这道题是三分.. { 我来告诉你世界的真相 = = 因为这题能最小费用最大流 每次最短路长度不降 所以是单峰的 最短路长度就是差分值.. 所以一阶导不降.. 是不是简单粗暴 你要证函数是单峰的. 当然是证斜率什么的 } 三分完初始买了多少个玩具,然后就是贪心. 首先我想说这个贪心真动规.虽然它真的是贪心. 首先先说一种错误的贪心. 就是从前往后扫,优先用

【POJ3659】【USACO 2008 Jan Gold】 3.Cell Phone Network 树上最小支配集/贪心 两种做法

题意:求树上最小支配集 最小支配集:点集,即每个点可以"支配"到相邻点,求最少点数可以使所有点被支配. 图上的最小支配集是NP的,但是树上的可以DP做,是O(n)的. 暴力做就好了, f[i]表示此 点被选时的子树全支配的最小代价 g[i]表示其父亲节 点被选时的子树全支配的最小代价 h[i]表示其某子节 点被选时的子树全支配的最小代价 然后暴力转移. (v是子节点) f[x]=∑(min(f[v],min(g[v],h[v])))+1; g[x]=∑(min(f[v],h[v]));

【POJ3666】【USACO 2008 Feb Gold】 2.Cow Game 动规

题意:有若干个数,然后可以花费i的代价让某个数+i或者-i. 现在要求让你把序列排成不升或者不降,问最小代价. 题解: 首先可以证明,最优花费下最后所有的数都可以是现在的某个数: 证:如果两个数调整后在两个数中间,那么可以把两个数都变为其中一个数,而代价显然是等同的. 这个出来后就好做了. 我们可以先离散化一下,然后f[i][j]表示第i个数变为j时1~i这些数保持非严格单调的最小花费 转移时f[i][j]不必n*n枚举,可以维护一个前缀最优(非常水),然后O(1)转移. 然后做一遍非升,一遍非

【BZOJ1589】【USACO 2008 Dec Gold】 1.Trick or Treat on the Farm 基环树裸DP、

没测样例一遍A这真是-- 题意:每个点都有且仅有一个出边(可以出现自环),然后这样一个点出发就会走过且一定走过某些点. 问每个点出发都会走过几个点. 首先这是基环树无疑. 然后就是裸DP了. 这个的关键就是找环,仅此. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 101000 using namespace std; int n

【POJ3657】【USACO 2008 Jan Gold】 1.Haybale Guessing 二分答案,并查集check

题意: 输入n.m表示数列长度为n,有m条有序的限制{l,r,x}. 限制:l~r间所有数最小值为x. 问到第几条限制开始出现矛盾,都不出现输出"0". 题解: 首先这题比较厉害,正常解有点难,不妨转化成二分答案. 我们二分"答案",也就是第ans条出现矛盾. 考虑到若一条限制S所在区间被另一个限制Seg包含,且Seg这条限制的x又比S.x大, 那么也就是意为 ① [Seg.l,Seg.r]间最小值为Seg.x ② [S  .l,S  .r]间最小值为S  .x ③

bzoj1597【USACO 2008 Mar】土地购买

1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3169  Solved: 1183 [Submit][Status][Discuss] Description 农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000). 每块

【POJ3658】【USACO 2008 Jan Gold】 2.Artificial Lake人工湖 单调栈

人工湖 Time Limit: 1 Sec  Memory Limit: 128 MB Description 夏日那让人喘不过气的酷热将奶牛们的烦躁情绪推到了最高点.最终,FJ 决定建一个人工湖供奶牛消暑之用.为了使湖看起来更加真实,FJ决定将湖的 横截面建成N(1 <= N <= 100,000)个连续的平台高低错落的组合状,所有的平台 从左到右按1..N依次编号.当然咯,在湖中注入水后,这些平台都将被淹没. 平台i在设计图上用它的宽度W_i(1 <= W_i <= 1,000