POJ 1789 解题报告

这道题是求最小生成树。很久之前是用kruskal算法求的(之前已经用过这个模板很多次),但是超时了,这里是稠密图,对所有边排序是非常耗时的操作。这里改用没有优化的prim算法(用的是数组而不是heap,这意味着每次选最近的节点都需要过一遍数组,O(N))。但是还是很轻松地通过了。

thestoryofsnow1789Accepted160K438MSC++1591B
/* 
ID: thestor1 
LANG: C++ 
TASK: poj1789 
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>

using namespace std;

const int MAXN = 2000;
bool inset[MAXN];
int dis[MAXN];

// each line is a 7-character string
// therefore, the maximum difference is 7
const int MAXDIFF = 7;
char lines[MAXN][MAXDIFF + 1];

int diff(int u, int v)
{
	int d = 0;
	for (int i = 0; lines[u][i] != '\0' && lines[v][i] != '\0'; ++i)
	{
		if (lines[u][i] != lines[v][i])
		{
			d++;
		}
	}
	return d;
}


int minu(const int N)
{
	int mindis = MAXDIFF, u = 0;
	for (int i = 0; i < N; ++i)
	{
		if (!inset[i] && dis[i] < mindis)
		{
			mindis = dis[i];
			u = i;
		}
	}
	return u;
}

int prim(const int N)
{
	for (int i = 0; i < N; ++i)
	{
		inset[i] = false;
	}
	
	for (int i = 0; i < N; ++i)
	{
		dis[i] = MAXDIFF;
	}

	int source = 0;
	dis[source] = 0;

	int mst = 0;
	for (int i = 0; i < N; ++i)
	{
		int u = minu(N);	
		inset[u] = true;
		mst += dis[u];

		for (int i = 0; i < N; ++i)
		{
			if (!inset[i])
			{
				int d = diff(u, i);
				if (d < dis[i])
				{
					dis[i] = d;
				}
			}
		}
	}

	return mst;
}

int main()
{
	int N;
	while (scanf("%d", &N) && N)
	{
		for (int i = 0; i < N; ++i)
		{
			scanf("%s", lines[i]);
		}

		// for (int i = 0; i < N; ++i)
		// {
		// 	printf("%s\n", lines[i]);
		// }

		printf("The highest possible quality is 1/%d.\n", prim(N));
	}

	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值