题意
给定一个完全图,图中有点权和边权, 找出m个点,构成的一棵树,使得他们的边权之和除以点权值和最小。
题解
最小生成树可以解决分子边权之和最小,又因为是稠密图,所以考虑Prim。
如何确定点权之和最小,由于是点数很少,直接暴力枚举即可。最差是
C715
C
15
7
。
代码
#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 200;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n, m, tot;
double ans = LINF,nowans;
int indexval[nmax];
int mp[nmax][nmax];
bool visit[nmax];
struct edge {
int to, w, from;
}e[nmax<<1];
vector<int> nodes;
void cal() {
double edgeval = 0, nodeval = 0;
bool book[20];
int dist[20], pre[20];
int start = -1, mindis, index;
for(int i = 1; i <= n; ++i){
book[i] = !visit[i];
if(visit[i] && start == -1) {
start = i;
}
}
book[start] = true;
nodeval += indexval[start];
for(int i = 1; i <= n; ++i) {
dist[i] = mp[start][i];
pre[i] = start;
}
for(int i = 1; i <= m-1; ++i) {
mindis = INF;
for(int j = 1; j <= n; ++j) {
if(book[j] == false && dist[j] < mindis) {
mindis = dist[j];
index = j;
}
}
book[index] = true;
nodeval += indexval[index];
edgeval += mp[pre[index]][index];
start = index;
for(int j = 1; j <= n; ++j) {
if(book[j] == false && mp[index][j] < dist[j]) {
dist[j] = mp[index][j];
pre[j] = start;
}
}
}
if(edgeval / nodeval < ans) {
ans = edgeval / nodeval;
nowans = edgeval / nodeval;
nodes.clear();
for(int i = 1; i <= n; ++i) {
if(visit[i]) {
nodes.push_back(i);
}
}
}
}
void dfs(int pos, int num) {
if(num > m) return;
if(pos == n + 1) {
if(num != m) return;
else {
cal();
// for(int i = 1; i <= n; ++i) {
// if(visit[i])
// printf("%d ",i);
// }
// printf("\n");
// printf("nowans %lf\n", nowans);
return;
}
}
visit[pos] = true;
dfs(pos+1, num+1);
visit[pos] = false;
dfs(pos+1, num);
}
int main() {
while(scanf("%d %d", &n, &m) != EOF) {
if(n == 0 && m == 0)
break;
tot = 0;
ans = LINF;
nodes.clear();
for(int i = 1; i <= n; ++i) {
scanf("%d", &indexval[i]);
}
int temp = 0;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= n; ++j) {
scanf("%d", &mp[i][j]);
}
}
dfs(1,0);
for(int i = 0; i < nodes.size(); ++i) {
if(!i) printf("%d",nodes[i]);
else printf(" %d",nodes[i]);
}
printf("\n");
}
return 0;
}