Minimal Ratio Tree
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1303 | Accepted: 479 |
Description
For a tree, which nodes and edges are all weighted, the ratio of it is calculated according to the following equation.
Given a complete graph of n nodes with all nodes and edges weighted, your task is to find a tree, which is a sub-graph of the original graph, with m nodes and whose ratio is the smallest among all the trees of m nodes in the graph.
Given a complete graph of n nodes with all nodes and edges weighted, your task is to find a tree, which is a sub-graph of the original graph, with m nodes and whose ratio is the smallest among all the trees of m nodes in the graph.
Input
Input contains multiple test cases. The first line of each test case contains two integers n (2<=n<=15) and m (2<=m<=n), which stands for the number of nodes in the graph and the number of nodes in the minimal ratio tree. Two zeros end the input. The next line contains n numbers which stand for the weight of each node. The following n lines contain a diagonally symmetrical n×n connectivity matrix with each element shows the weight of the edge connecting one node with another. Of course, the diagonal will be all 0, since there is no edge connecting a node with itself.
All the weights of both nodes and edges (except for the ones on the diagonal of the matrix) are integers and in the range of [1, 100].
The figure below illustrates the first test case in sample input. Node 1 and Node 3 form the minimal ratio tree.
All the weights of both nodes and edges (except for the ones on the diagonal of the matrix) are integers and in the range of [1, 100].
The figure below illustrates the first test case in sample input. Node 1 and Node 3 form the minimal ratio tree.
Output
For each test case output one line contains a sequence of the m nodes which constructs the minimal ratio tree. Nodes should be arranged in ascending order. If there are several such sequences, pick the one which has the smallest node number; if there's a tie, look at the second smallest node number, etc. Please note that the nodes are numbered from 1.
Sample Input
3 2 30 20 10 0 6 2 6 0 3 2 3 0 2 2 1 1 0 2 2 0 0 0
Sample Output
1 3 1 2
Source
先从点数中选出m个点(C(m,n),利用dfs),此时点的权值和已经确定,然后对于这m个点做最小生成树,得到最小ratio值。
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#include <iomanip>
#include <map>
#include <stack>
#include <functional>
#include <list>
using namespace std;
#define MAX_POINT_NUM 30
#define INF 2000000000
int n, m;
vector<int> vp;
int cost[MAX_POINT_NUM][MAX_POINT_NUM];
vector<vector<int> > p;
vector<bool> used;
void dfs(int pos, int num) {
if (num == m) {
vector<int> one;
for (int i = 0; i < used.size(); i++) {
if (used[i]) {
one.push_back(i);
}
}
p.push_back(one);
return;
}
if (pos == n) return;
used[pos] = true;
dfs(pos + 1, num + 1);
used[pos] = false;
dfs(pos + 1, num);
}
void getPoints() {
p.clear();
used.resize(n);
for (int i = 0; i < n; i++) used[i] = false;
dfs(0, 0);
}
int mincost[MAX_POINT_NUM];
bool vis[MAX_POINT_NUM];
int prim(int k) {
for (int i = 0; i < p[k].size(); i++) {
mincost[p[k][i]] = INF;
vis[p[k][i]] = false;
}
mincost[p[k][0]] = 0;
int res = 0;
while (1) {
int v = -1;
for (int u = 0; u < p[k].size(); u++) {
if (!vis[p[k][u]] && (v == -1 || mincost[p[k][u]] < mincost[v])) v = p[k][u];
}
if (v == -1) break;
vis[v] = true;
res += mincost[v];
for (int u = 0; u < p[k].size(); u++) {
mincost[p[k][u]] = min(mincost[p[k][u]], cost[v][p[k][u]]);
}
}
return res;
}
int main() {
std::ios::sync_with_stdio(false);
while (1) {
cin >> n >> m;
if (n == 0 && m == 0) break;
vp.resize(n);
getPoints();
//sort(p.begin(), p.end());
for (int i = 0; i < n; i++) cin >> vp[i];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> cost[i][j];
}
}
float ans = INF;
int ansPos;
for (int i = 0; i < p.size(); i++) {
int sump = 0;
for (int j = 0; j < p[i].size(); j++) sump += vp[p[i][j]];
int pr = prim(i);
float now = 1.0 * pr / sump;
if (now < ans) {
ans = now;
ansPos = i;
}
}
for (int i = 0; i < p[ansPos].size(); i++) {
cout << p[ansPos][i] + 1 << " ";
}
cout << endl;
}
//getchar();
//getchar();
return 0;
}