最小生成树

poj 1789

2018-03-01  本文已影响0人  failed

题目可能有点难读懂,copy一下别人的讲解,这个题还是个简单的最小生成树。

题意:用一个7位的字符串代表一个编号,这两个编号之间不同字母的个数等于两个编号之间的距离。一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的distance,现在要找出一个“衍生”方案,使得总代价最小,也就是distance之和最小。
案例说明:
1.aaaaaaa
2.baaaaaa
3.abaaaaa
4.aabaaaa
1和2,3,4之间的距离都为1,2和3的距离为2,2和4的距离为2,3和4的距离为2.
显然的,第二,第三和第四编号分别从第一编号衍生出来的代价最小,因为第二,第三和第四编号分别与第一编号只有一个字母是不同的,相应的distance都是1,加起来是3。也就是最小代价为3。
问题可以转化为最小代价生成树的问题。

#include <cstdio>
#include <cstring>
#include <iostream>
#define MAX 2010

using namespace std;
int n;
char str[MAX][8];
int map[MAX][MAX];
int low[MAX];
int visit[MAX];
int prim() {
  memset(visit, 0, sizeof(visit));
  int sum = 0;
  visit[0] = 1;
  for (int i = 0; i < n; i++) {
    if (visit[i])
      continue;
    low[i] = map[0][i];
  }
  for (int i = 0; i < n - 1; i++) {
    int minn = 0x3f3f3f3f;
    int u;
    for (int j = 0; j < n; j++) {
      if (low[j] < minn && !visit[j]) {
        minn = low[j];
        u = j;
      }
    }
    sum += minn;
    visit[u] = 1;

    for (int j = 0; j < n; j++) {
      if (low[j] > map[u][j] && !visit[j])
        low[j] = map[u][j];
    }
  }

  return sum;
}

int main(int argc, char const *argv[]) {
  while (~scanf("%d", &n) && n) {
    memset(map, 0, sizeof(map));
    for (int i = 0; i < n; i++) {
      scanf("%s", str[i]);
    }

    for (int i = 0; i < n - 1; i++) {
      for (int j = i + 1; j < n; j++) {
        for (int k = 0; k < 7; k++) {
          if (str[i][k] != str[j][k]) {
            map[i][j]++;
            map[j][i] = map[i][j];
          }
        }
      }
    }

    printf("The highest possible quality is 1/%d.\n", prim());
  }
  return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读