现在的位置: 首页 > 综合 > 正文

POJ 1789 Truck History (最小生成树)

2018年01月14日 ⁄ 综合 ⁄ 共 1015字 ⁄ 字号 评论关闭

题目类型  最小生成树

题目意思
给出最多2000个长度为7的字符串, 现在要求除了某个字符串外每一个字符串都必须找一个源子符串, 使从源字符串转化出其他的字符串的总代价最小
假设 abaaaaa 的源子符串是 aaaaaaa 的话那么从 aaaaaaa 转化出 abaaaaa 的代价就是不同字符的位数(这个例子就只有1位不同 代价为1)

解题方法
很明显的最小生成树 每个字符串为一个点 字符串间的转化的代价为 边 的权值 最小生成树对应的边权和即为最小代价
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
以下代码用的是kruscal算法 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 2000 + 10;
char str[maxn][10];
int f[maxn];

struct Node {
	int u, v, w;
	bool operator < (const Node & rhs) const {
		return w < rhs.w;
	}
}E[maxn*maxn];

int diff(int a, int b) {
	int res = 0;
	for( int i=0; i<7; i++ ) {
		if(str[a][i] != str[b][i]) res++;
	}
	return res;
}

int find(int x) {
	return f[x] == x ? x : find(f[x]);
}

int main() {
	freopen("in", "r", stdin);
	int n;
	while(scanf("%d", &n), n) {
		for( int i=0; i<n; i++ ) {
			scanf("%s", str[i]);
			f[i] = i;
		}
		int k = 0;
		for( int i=0; i<n; i++ ) {
			for( int j=i+1; j<n; j++ ) {
				E[k].u = i; E[k].v = j; E[k].w = diff(i, j);
				k++;
			}
		}
		sort(E, E+k);
		int res = 0;
		int tn = n;
		for( int i=0; i<k; i++ ) {
			int u = E[i].u, v = E[i].v;
			int x = find(u), y = find(v);
			if(x != y) {
				res += E[i].w;
				f[x] = y;
				tn--;
				if(tn == 1) break;
			}
		}
		printf("The highest possible quality is 1/%d.\n", res);
	}
	return 0;
}

抱歉!评论已关闭.