POJ 3228 - Gold Transportation
http://poj.org/problem?id=3228
概要
N 個の街が M 本の道(双方向)で繋がれている. 金鉱も倉庫も街に存在し,金鉱からとれたすべての金を倉庫までトラックで運ぶ. 金鉱には金の量が,倉庫には倉庫の容量が設定されている.
トラックの運転手は bad temper なことで有名で,街から街へ移動するたびに休憩をとる. そこで,金を運ぶ際に通る道の長さの最大値を最小化したい. そのときの最小値を答える.
ただし,すべての金を倉庫まで運べないときは「No Solution」と出力する.
制約
- 1 <= N <= 200
- 0 <= M <= (N-1)*N/2
- 0 < 道の長さ <= 10000
解法
長さが K 以下の道のみを使って題意を満たせるかどうかを判定して,K について二分探索.
判定は,各連結成分の中で 金の量の合計 <= 倉庫の容量の合計 となっているかどうかを調べればいい.
poj/3228.cc1 #include <cstdio> 2 #include <vector> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 7 bool ok(const vector<vector<pair<int,int> > >& g, const vector<int>& gold, int K) 8 { 9 const int N = g.size(); 10 vector<int> visited(N, false); 11 for (int i = 0; i < N; i++) { 12 if (visited[i]) { 13 continue; 14 } 15 queue<int> q; 16 q.push(i); 17 visited[i] = true; 18 int c = 0; 19 while (!q.empty()) { 20 const int n = q.front(); 21 q.pop(); 22 c += gold[n]; 23 for (vector<pair<int,int> >::const_iterator it = g[n].begin(); it != g[n].end(); ++it) { 24 const int m = it->first; 25 const int d = it->second; 26 if (d <= K && !visited[m]) { 27 visited[m] = true; 28 q.push(m); 29 } 30 } 31 } 32 if (c > 0) { 33 return false; 34 } 35 } 36 return true; 37 } 38 39 int main() 40 { 41 int N; 42 while (scanf("%d", &N) != EOF && N != 0) { 43 vector<int> gold(N, 0); 44 for (int i = 0; i < N; i++) { 45 int c; 46 scanf("%d", &c); 47 gold[i] += c; 48 } 49 for (int i = 0; i < N; i++) { 50 int c; 51 scanf("%d", &c); 52 gold[i] -= c; 53 } 54 vector<vector<pair<int,int> > > g(N); 55 int M; 56 scanf("%d", &M); 57 for (int i = 0; i < M; i++) { 58 int u, v, d; 59 scanf("%d %d %d", &u, &v, &d); 60 --u; --v; 61 g[u].push_back(make_pair(v, d)); 62 g[v].push_back(make_pair(u, d)); 63 } 64 65 static const int INF = 1000000; 66 int left = 0, right = INF; 67 while (left < right) { 68 const int mid = (left + right)/2; 69 if (ok(g, gold, mid)) { 70 right = mid; 71 } else { 72 left = mid+1; 73 } 74 } 75 if (left == INF) { 76 puts("No Solution"); 77 } else { 78 printf("%d\n", left); 79 } 80 } 81 return 0; 82 }