UVA 1494 - Qin Shi Huang's National Road System(次小生成树)

题目链接:点击打开链接

题意:n个城市,需要修建一些道路使得任意两个城市联通,还可以修一条魔法道路, 不花钱, 设魔法路连接的城市的人口之和为A, 所有道路总长为B, 求A/B的最大值。

思路: 次小生成树。 先做一次最小生成树, 然后用dfs搜索出最小生成树上任意两点之间最长的道路长度。  然后枚举在哪两个城市之间建魔法道路。n^2复杂度。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 1000000000;
const int maxn = 1000 + 10;
int T,n,m,cnt,p[maxn];
double val[maxn][maxn],d[maxn][maxn];
bool vis[maxn];
struct node {
    double x, y, p;
}a[maxn];
struct Edge {
    int a, b;
    double c;
    Edge(int a=0,int b=0,double c=0):a(a), b(b), c(c) {}
    bool operator < (const Edge& rhs) const {
        return c < rhs.c;
    }
}edges[maxn*maxn];
vector<int> g[maxn];
int _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }
void dfs(int root, int cur) {
    vis[cur] = true;
    int len = g[cur].size();
    for(int i=0;i<len;i++) {
        int v = g[cur][i];
        if(!vis[v]) {
            val[root][v] = max(val[root][cur], d[cur][v]);
            dfs(root, v);
        }
    }
}
double solve() {
    sort(edges, edges + cnt);
    for(int i=1;i<=n;i++) p[i] = i, g[i].clear();
    double minv = 0;
    for(int i=0;i<cnt;i++) {
        int x = _find(edges[i].a);
        int y = _find(edges[i].b);
        if(x != y) {
            p[x] = y;
            g[edges[i].a].push_back(edges[i].b);
            g[edges[i].b].push_back(edges[i].a);
            d[edges[i].a][edges[i].b] = d[edges[i].b][edges[i].a] = edges[i].c;
            minv += edges[i].c;
        }
    }
    for(int i=1;i<=n;i++) {
        memset(vis, false, sizeof(vis));
        dfs(i, i);
    }
    double ans = 0;
    for(int i=1;i<=n;i++) {
        for(int j=i+1;j<=n;j++) {
            double A = a[i].p + a[j].p;
            double B = minv - val[i][j];
            ans = max(ans, A/B);
        }
    }
    return ans;
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
            scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].p);
        }
        cnt = 0;
        for(int i=1;i<=n;i++) {
            for(int j=i+1;j<=n;j++) {
                double dist = sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x) + (a[i].y-a[j].y)*(a[i].y-a[j].y));
                edges[cnt++] = Edge(i, j, dist);
            }
        }
        printf("%.2f\n",solve());
    }
    return 0;
}


你可能感兴趣的:(uva,ACM-ICPC,次小生成树)