HDU 4081 Qin Shi Huang‘s National Road System (次小生成树)

题意:给出n个城市的x,y坐标以及每个城市的人数, 这些城市的主人想建造最小生成树,这时候有个会魔法的道士说, 我可以让一条路权值为0, 求A/B的最大值, 其中A是权值为0的道路连接的两个城市的人数之和, B是最小生成树的权值。

题解:次小生成树
先求一遍mst,有一点跟次小生成树不同的是,若是mst上的边,也可以将其边权置为0。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int maxn = 1e3 + 5;
int t, n, x[maxn], y[maxn], p[maxn];
const int INF = 0x3f3f3f3f;
bool vis[maxn], used[maxn][maxn];
int pre[maxn];
double cost[maxn][maxn], lowc[maxn];
double Max[maxn][maxn];//Max[i][j] 表示在最小生成树中从 i 到 j 的路径中的最大边权
double Prim(int n) {
    
    
	double ans = 0;
	memset(vis, false, sizeof(vis));
	memset(Max, 0, sizeof(Max));
	memset(used, false, sizeof(used));
	vis[0] = true;
	pre[0] = -1;
	for (int i = 1; i < n; i++) {
    
    
		lowc[i] = cost[0][i];
		pre[i] = 0;
	}
	lowc[0] = 0;
	for (int i = 1; i < n; i++) {
    
    
		double minc = INF;
		int p = -1;
		for (int j = 0; j < n; j++)
			if (!vis[j] && minc > lowc[j]) {
    
    
				minc = lowc[j];
				p = j;
			}
		if (minc == INF) return -1;
		ans += minc;
		vis[p] = true;
		used[p][pre[p]] = used[pre[p]][p] = true;
		for (int j = 0; j < n; j++) {
    
    
			if (vis[j] && j != p) Max[j][p] = Max[p][j] = max(Max[j][pre[p]], lowc[p]);
			if (!vis[j] && lowc[j] > cost[p][j]) {
    
    
				lowc[j] = cost[p][j];
				pre[j] = p;
			}
		}
	}
	return ans;
}
double dis(int xa, int ya, int xb, int yb) {
    
    
	return sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
}
int main() {
    
    
	scanf("%d", &t);
	while (t--) {
    
    
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) {
    
    
			scanf("%d%d%d", &x[i], &y[i], &p[i]);
		}
		memset(cost, 0x3f, sizeof(cost));
		for (int i = 1; i <= n; i++) {
    
    
			for (int j = i + 1; j <= n; j++) {
    
    
				cost[i - 1][j - 1] = cost[j - 1][i - 1] = dis(x[i], y[i], x[j], y[j]);
			}
		}
		double ans = Prim(n);
		double ans2 = -1;
		for (int i = 1; i <= n; i++) {
    
    
			for (int j = i + 1; j <= n; j++) {
    
    
				double temp = used[i - 1][j - 1] ? ans - cost[i - 1][j - 1] : ans - Max[i - 1][j - 1];
				ans2 = max(ans2, 1.0 * (p[i] + p[j]) / temp);
			}
		}
		printf("%.2f\n", ans2);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43680965/article/details/107800571