HDU 4081 Qin Shi HuangのNational Road System(サブスモールスパニングツリー)

質問の意味:n個の都市のx、y座標と各都市の人々の数を考慮して、これらの都市の所有者は最小全域木を構築したいと考えています。現時点では、不思議な道教は、道路の右の値を0にすることができます、 A / Bの最大値を見つけます。Aは、重み0の道路で接続された2つの都市の人数の合計で、Bは最小全域木の重みです。

問題の解決策:2番目に小さいスパニングツリー
まずmstを探します。2番目に小さいスパニングツリーと異なる点の1つは、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