1. 程式人生 > >[洛谷P1550] [USACO08OCT]打井Watering Hole [最小生成樹]

[洛谷P1550] [USACO08OCT]打井Watering Hole [最小生成樹]

題目背景

John的農場缺水了!!!

題目描述

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)。

輸出格式:

只有一行,為一個整數,表示所需要的錢數。

第一眼以為是個DP  但是發現有後效性

有點像網路流的思想   我們得有一個源泉 那就是井  而且必須有一口井

所以我們把井當做一個點  把它與所有點連邊  邊權為在那個點打井的費用

然後各個點連引水邊

跑一次最小生成樹 就OK了

原始碼

#include <bits/stdc++.h>
using namespace std; int top, n, fa[305], fe[305], mp[305][305], head[305]; struct Node { int x, y, nxt, w; Node() { } Node( int x, int y, int w, int nxt ) : x(x), y(y), w(w), nxt(nxt) { } inline bool operator < ( const Node &a ) const { return w < a.w; } } e[150005]; inline void Adde( int x, int y, int w ) { e[++top] = Node(x, y, w, head[x]), head[x] = top; e[++top] = Node(y, x, w, head[y]), head[y] = top; } int Find( int x ) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } int main() { cin >> n; for(int i = 1; i <= n; ++i) fa[i] = i, scanf( "%d", &fe[i] ); for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) scanf( "%d", &mp[i][j] ); for(int i = 1; i <= n; ++i) for(int j = i + 1; j <= n; ++j) Adde(i, j, mp[i][j]); for(int i = 1; i <= n; ++i) Adde(0, i, fe[i]); sort(e + 1, e + top + 1); long long ans = 0; for(int i = 1; i <= top; ++i) { int u = Find(e[i].x), v = Find(e[i].y); if(u != v) { fa[u] = v; ans += e[i].w; } } cout << ans << endl; return 0; }