POJ 3925 - Minimal Ratio Tree
http://poj.org/problem?id=3925
概要
すべてのノードとエッジに重みがある木に対して,ratio を
Ratio := Σedge_weight / Σnode_weight
と定める.
与えられた n 個のノードからなる重み付きグラフのサブグラフのうち,m 個のノードからなる ratio が最小の木を答える.
制約
- 2 <= m <= n <= 15
解法
m 個のノードの選び方は全探索.
すると Σnodeweight が決まるので,Ratio を小さくするには Σedgeweight を小さくすればよい. これは最小全域木を求めればいい.
poj/3925.cc1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <iterator> 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 typedef int weight_type; 50 weight_type w; 51 edge(int s, int d, weight_type w_) : u(s), v(d), w(w_) {} 52 bool operator<(const edge& that) const { return w < that.w; } 53 };/*}}}*/ 54 55 int main() 56 { 57 int n, m; 58 while (cin >> n >> m && n != 0) { 59 vector<int> weights(n); 60 for (int i = 0; i < n; i++) { 61 cin >> weights[i]; 62 } 63 vector<edge> edges; 64 for (int i = 0; i < n; i++) { 65 for (int j = 0; j < n; j++) { 66 int w; 67 cin >> w; 68 if (i < j) { 69 edges.push_back(edge(i, j, w)); 70 } 71 } 72 } 73 sort(edges.begin(), edges.end()); 74 75 vector<bool> use(n, false); 76 for (int i = 0; i < m; i++) { 77 use[i] = true; 78 } 79 sort(use.begin(), use.end()); 80 int min_ew = 0, min_nw = 0; 81 vector<int> ans; 82 do { 83 int nw = 0; 84 vector<int> nodes; 85 for (int i = 0; i < n; i++) { 86 if (use[i]) { 87 nw += weights[i]; 88 nodes.push_back(i+1); 89 } 90 } 91 92 // kruskal 93 DisjointSet s(n); 94 int ew = 0; 95 for (vector<edge>::const_iterator it(edges.begin()); it != edges.end(); ++it) { 96 if (use[it->u] && use[it->v] && s.unite(it->u, it->v)) { 97 ew += it->w; 98 if (s.size(it->u) == m) { 99 if (min_nw == 0 || ew*min_nw <= min_ew*nw) { 100 min_ew = ew; 101 min_nw = nw; 102 ans = nodes; 103 } 104 break; 105 } 106 } 107 } 108 } while (next_permutation(use.begin(), use.end())); 109 copy(ans.begin(), ans.end(), ostream_iterator<int>(cout, " ")); 110 cout << endl; 111 } 112 return 0; 113 }