版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wlh1998/article/details/76164940
#include<stdio.h>
#include<string.h>
const int INF = 0x3f3f3f3f;
const int maxn = 22;
int mps[maxn][maxn]; // 存图;
int mp[maxn][maxn];
int pw[maxn]; // 点权
int vis[maxn]; //是否在新图内;
int dis[maxn]; //第i个顶点到新图最短距离;
int prim(int n);
int ans[maxn];
int n, m,sum1,sum2;
int p[maxn];
void dfs(int pos, int k){
if (k == m){
int sumt1 = prim(m); //边权和
int sumt2 = 0; //点权和
for (int i = 0; i < m; i++){
sumt2 += pw[p[i]];
}
if (sum2 == -1 || sumt1*sum2 < sum1*sumt2){ //不可将sum1设INF判断,乘法可能会爆数据
sum1 = sumt1;
sum2 = sumt2;
for (int i = 0; i < m; i++){
ans[i] = p[i] + 1; //题目从1到n输入;
}
}
}
if (n - pos + k < m) return; //?
for (int i = pos; i < n; i++){
p[k] = i;
dfs(i+1,k+1);
}
}
int main (){
while (scanf("%d%d", &n, &m) != EOF && n != 0){
memset(mp, 0, sizeof(mp));
for (int i = 0; i < n; i++){
scanf("%d", &pw[i]);
}
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
scanf("%d",&mps[i][j]);
}
}
sum1 = 100000;
sum2 = -1;
memset(ans,0,sizeof(ans));
dfs(0,0);
printf("%d",ans[0]);
for (int i = 1; i < m; i++){
printf(" %d",ans[i]);
}
printf("\n");
}
}
int prim(int n){
int ans = 0;
memset(vis,0,sizeof(vis));
for (int i = 0; i < m; i++){
for (int j = 0; j < m; j++){
mp[i][j] = mps[p[i]][p[j]];
}
}
vis[0] = 1; //注意第一个点的初始化;
for (int i = 0; i < n; i++) dis[i] = mp[0][i]; // 新图第一个点为0,初始化dis;
for (int i = 1; i < n; i++){ // 加入第i+1个点
int minn = INF ; // 旧图到新图最短距离
int pos = -1; // 旧图最近点标号;
for (int j = 0; j < n; j++){
if(!vis[j] && minn > dis[j]) {
minn = dis[j];
pos = j;
}
}
if (minn == INF) return -1;
ans += minn; //更新答案;
vis[pos] = 1;
for (int j = 0; j < n; j++) {
if (!vis[j] && mp[pos][j] < dis[j]){
dis[j] = mp[pos][j];
}
}
}
return ans;
}