zl程序教程

您现在的位置是:首页 >  其他

当前栏目

HDU 4081Qin Shi Huang's National Road System(最小生成树+最小瓶颈路)

amp 生成 39 HDU 最小 system 瓶颈
2023-09-27 14:25:13 时间


题意:秦始皇要修路。把N个城市用N-1条边连通。且他希望花费最小,可是这时候有一个多管闲事的道士出来说他有魔法能够帮助秦始皇变成一条路。可是仅仅能变出一条。

可是。两个人对修路的法案存在歧义,道士希望修路能够给很多其它的百姓带来福利。而秦始皇希望修路要尽量使花费小。最后,秦始皇拿出了一个公式A/B。A表示两个城市的人数,B表示出了用魔法变出来的路外。最短的总距离。

如今要你求出A/B的最大值。

思路:枚举连接哪两个城市。由于这条边是免费的。我们要求算上这条边的最小生成树。假设每次都求一次最小生成树会超时,所以先跑一遍整个图的最小生成树。然后再预处理出这个mst上的随意两点之间路径的最大值,由于加入免费边时,去掉的就是这个最大边。这样一样时间复杂度降为O(n*n)。

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
#include<set>
#define eps 1e-6 
#define LL long long  
using namespace std;  

const int maxn = 1050;
const int maxm = maxn*maxn;
//const int INF = 0x3f3f3f3f;
vector<int> G[maxn];
int vis[maxn];
int n, m, ple[maxn], x[maxn], y[maxn];
int u[maxm], v[maxm], p[maxn], r[maxm];
double w[maxm], W[maxn][maxn], maxcost[maxn][maxn];;
bool cmp(const int i, const int j) {
	return w[i] < w[j];
} 
int find(int x) {
	return p[x] == x ? x : p[x] = find(p[x]);
}
double Kruscal() {
	double ans = 0;
	for(int i = 0; i < n; i++) p[i] = i; //初始化并查集 
	for(int i = 0; i < m; i++) r[i] = i; //初始化边序号
	sort(r, r+m, cmp);
	for(int i = 0; i < m; i++) {
		int e = r[i]; 
		int x = find(u[e]), y = find(v[e]);
		if(x != y) {
			ans += w[e];
			p[x] = y;
			G[u[e]].push_back(v[e]); G[v[e]].push_back(u[e]);
		}
	}
	return ans;
}
void init() {
	memset(vis, 0, sizeof(vis));
	for(int i = 0; i < n; i++) G[i].clear();
}
void dfs(int cur, int fa) {
	maxcost[cur][cur] = 0;
	if(fa != -1) {
		for(int i = 0; i < n; i++) if(vis[i]){
			maxcost[i][cur] = maxcost[cur][i] = max(maxcost[i][fa], W[fa][cur]);
		}
	}
	vis[cur] = 1;
	for(int i = 0; i < G[cur].size(); i++) {
		int u = G[cur][i];
		if(u == fa) continue;
		dfs(u, cur);
	}
}
int main() {
	//freopen("input.txt", "r", stdin);
	int T; cin >> T;
	while(T--) {
		cin >> n;
		for(int i = 0; i < n; i++) scanf("%d%d%d", &x[i], &y[i], &ple[i]);
		m = 0;
		for(int i = 0; i < n; i++) {
			for(int j = i+1; j < n; j++) {
				u[m] = i; v[m] = j;
				w[m] = sqrt((double)((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
				W[i][j] = W[j][i] = w[m];
				m++;
			}
		}
		init();
		double mst = Kruscal(); 
		//cout << mst << endl;
		dfs(0, -1);
		double ans = 0;
		for(int i = 0; i < n; i++) {
			for(int j = i+1; j < n; j++) {
				ans = max(ans, (double)(ple[i]+ple[j])/(mst-maxcost[i][j]));
			}
		}
		printf("%.2lf\n", ans);
	} 
	return 0;
}