POJ 1639 - Picnic Planning
http://poj.org/problem?id=1639
概要
M 本の道が公園と N 人の家を繋いでいる.
K 台までの車を使って N 人全員が公園に行けるようにしたい. そのときの車の走行距離の合計の最小値を答える.
ただし,1台の車に何人でも乗ることができるとする.
制約
- M <= 20
- 人の名前は10文字以下
解法
公園からの枝を K 本まで使って最小全域木を作ればいい. M が小さいので,K 本の枝の選び方は全通り試しても問題無い.
poj/1639.cc1 #include <iostream> 2 #include <vector> 3 #include <map> 4 #include <algorithm> 5 using namespace std; 6 7 class DisjointSet/*{{{*/ 8 { 9 private: 10 vector<int> parent; 11 12 int root(int x) 13 { 14 if (parent[x] < 0) { 15 return x; 16 } else { 17 parent[x] = root(parent[x]); 18 return parent[x]; 19 } 20 } 21 22 public: 23 explicit DisjointSet(int n) : parent(n, -1) {} 24 25 bool unite(int x, int y) 26 { 27 const int a = root(x); 28 const int b = root(y); 29 if (a != b) { 30 if (parent[a] < parent[b]) { 31 parent[a] += parent[b]; 32 parent[b] = a; 33 } else { 34 parent[b] += parent[a]; 35 parent[a] = b; 36 } 37 return true; 38 } else { 39 return false; 40 } 41 } 42 43 bool find(int x, int y) { return root(x) == root(y); } 44 int size(int x) { return -parent[root(x)]; } 45 };/*}}}*/ 46 47 struct edge { 48 int u, v; 49 int w; 50 edge(int s, int d, int w_) : u(s), v(d), w(w_) {} 51 bool operator<(const edge& that) const { return w < that.w; } 52 }; 53 54 int kruskal(const vector<edge>& edges, const int N, const vector<int>& avail) 55 { 56 DisjointSet s(N); 57 int ttl = 0; 58 const int M = edges.size(); 59 for (int i = 0; i < M && s.size(0) < N; i++) { 60 if (avail[i] && s.unite(edges[i].u, edges[i].v)) { 61 ttl += edges[i].w; 62 } 63 } 64 if (s.size(0) == N) { 65 return ttl; 66 } else { 67 return 10000000; 68 } 69 } 70 71 int numbering(map<string,int>& m, const string& name) 72 { 73 const map<string,int>::const_iterator it = m.find(name); 74 if (it == m.end()) { 75 const int n = m.size(); 76 m.insert(make_pair(name, n)); 77 return n; 78 } else { 79 return it->second; 80 } 81 } 82 83 int main() 84 { 85 int M; 86 cin >> M; 87 map<string, int> m; 88 vector<edge> edges; 89 for (int i = 0; i < M; i++) { 90 string s1, s2; 91 int w; 92 cin >> s1 >> s2 >> w; 93 const int u = numbering(m, s1); 94 const int v = numbering(m, s2); 95 edges.push_back(edge(u, v, w)); 96 } 97 sort(edges.begin(), edges.end()); 98 const int N = m.size(); 99 int K; 100 cin >> K; 101 102 const int root = m["Park"]; 103 vector<int> v; 104 for (int i = 0; i < M; i++) { 105 if (edges[i].u == root || edges[i].v == root) { 106 v.push_back(i); 107 } 108 } 109 const int size = v.size(); 110 111 vector<int> avail(M, 1); 112 vector<int> a(size, 0); 113 for (int i = 0; i < min(size, K); i++) { 114 a[i] = 1; 115 } 116 sort(a.begin(), a.end()); 117 int ans = 10000000; 118 do { 119 for (int i = 0; i < size; i++) { 120 avail[v[i]] = a[i]; 121 } 122 ans = min(ans, kruskal(edges, N, avail)); 123 } while (next_permutation(a.begin(), a.end())); 124 125 cout << "Total miles driven: " << ans << endl; 126 return 0; 127 }