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

秦始皇统一中国之后要在全国修公路连接各个城市,皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城市人口/(生成树长度-这条路的长度(连接两个城市的路中,权值最大的那段路)))的路让他变,求这个比值最大值。 

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 1010, INF = 0x7fffffff;
int n;
int pre[maxn], vis[maxn];
double graph[maxn][maxn], maxd[maxn][maxn], d[maxn];
struct node
{
    int x, y, p;
}Node[maxn];

double prime(int s)
{
    double sum = 0;
    mem(vis, 0);
    mem(maxd, 0);
    int temp;
    rap(i, 1, n) d[i] = graph[s][i], pre[i] = s;
    d[s] = 0;
    vis[s] = 1;
    rap(i, 1, n-1)
    {
        double mincost = INF;
        rap(j, 1, n)
            if(!vis[j] && mincost > d[j])
            {
                temp = j;
                mincost = d[j];
            }
        rap(j, 1, n)
            if(vis[j] && j != temp) maxd[temp][j] = maxd[j][temp] = max(mincost, maxd[pre[temp]][j]);
        sum += mincost;
        vis[temp] = 1;
    //    used[temp][pre[temp]] = used[pre[temp]][temp] = 1;
        rap(j, 1, n)
        {
            if(!vis[j] && d[j] > graph[temp][j])
                d[j] = graph[temp][j], pre[j] = temp;
        }
    }
    return sum;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
 //求次小生成树还是得需要这段代码,用来找到不在生成树里的边
//        scanf("%d", &n);
//        for(int i=1; i<=n; i++)
//            for(int j=1; j<=n; j++)
//                if(i == j) graph[i][j] = 0;
//                else graph[i][j] = graph[j][i] = INF;
        rap(i, 1, n)
        {
            scanf("%d%d%d", &Node[i].x, &Node[i].y, &Node[i].p);
        }
        rap(i, 1, n)
            rap(j, i+1, n)
                graph[i][j] = graph[j][i] = sqrt((double)(Node[i].x - Node[j].x)*(Node[i].x - Node[j].x) + (double)(Node[i].y - Node[j].y)*(Node[i].y - Node[j].y));
        double dis = prime(1);
        double sum = -1;
        rap(i, 1, n)
            rap(j, i+1, n)
                if(pre[i] == j || pre[j] == i)   //对于当前结点i和j 如果i和j之间有直接边(在生成树中的) 则dis减直接边
                    sum = max(sum, 1.0*(Node[i].p + Node[j].p)/(dis - graph[i][j]));
                else                             //没有直接边 则减i和j之间那条路中权值最大的那段路
                    sum = max(sum, 1.0*(Node[i].p + Node[j].p)/(dis - maxd[i][j]));
        printf("%.2f\n", sum);

    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9415879.html