这题可以算是MST的变形,首先求MST,作用是枚举每条边。然后A = 左子树最大值 + 右子树最大值,B = 余下长度,注意枚举的那条边不是题目中的特殊边,因为如果这样想就变成了B固定,求A的最优值,而题目中A和B都是变量,互相牵制。
我在这里不是枚举边,这样做太麻烦了,改成枚举任意两点,dfs求出两点之间边权最大的边,把它替换了。
额。。。写的有点搓,各位尽情bs吧
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen("input.txt","r",stdin)
#define FF freopen("output.txt","w",stdout)
#define N 1005
double max(double a, double b){return a>b?a:b;}
double dis[N];
double g[N][N];
double d[N][N];
bool vis[N];
double maxx[N][N];
vector<int> v[N];
struct node {
double x, y;
int num;
}p[N];
double diss(node a, node b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
void dfs(int gg,int x,double maxm) {
int i;
vis[x] = 1;
for(i = 0; i < v[x].size(); i++) {
int y = v[x][i];
if (!vis[y]) {
maxm = max(maxm,g[x][y]);
maxx[gg][y] = maxx[y][gg] = maxm;
dfs(gg,y,maxm);
}
}
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
int n;
scanf("%d",&n);
int i,j;
for (i = 1;i <= n; i++) {
scanf("%lf%lf%d",&p[i].x, &p[i].y, &p[i].num);
v[i].clear();
}
memset(dis,MAX,sizeof(dis));
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
d[i][j] = d[j][i] = diss(p[i], p[j]);
g[i][j] = g[j][i] = 0;
}
}
for (i = 1; i <= n; i++) {
dis[i] = d[1][i];
vis[i] = 0;
}
vis[1] = 1;
int now = 1;
double sum = 0;
for (i = 1;i < n; i++) {
double minm = MAX;
int k = -1;
for (j = 1; j <= n; j++) {
if(dis[j] < minm && !vis[j]) {
k = j;
minm = dis[j];
}
}
if(k != -1) {
vis[k] = 1;
g[k][now] = g[now][k] = minm;
v[k].push_back(now);
v[now].push_back(k);
now = k;
sum += dis[k];
for (j = 1; j <= n; j++) {
if(!vis[j] && d[k][j] < dis[j]) {
dis[j] = d[k][j];
}
}
}
}
for (i = 1; i <= n; i++) {
memset(vis,0,sizeof(vis));
vis[i] = 1;
int next = v[i][0];
maxx[i][next] = g[i][next];
maxx[next][i] = g[next][i];//就是这里wa!!!无向的!!!
dfs(i,next,g[i][next]);
}
double ans = MIN;
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if(i == j)continue;
int A = p[i].num + p[j].num;
double res = (double)A / (sum - maxx[i][j]);
ans = max(ans, res);
}
}
printf("%.2f\n",ans);
}
return 0;
}
本文探讨了一种MST的变形算法,通过枚举任意两点间边权最大的边进行替换,来解决特定问题。算法涉及无向图、DFS、枚举技巧等核心概念,旨在优化路径选择。

被折叠的 条评论
为什么被折叠?



