hdu4081

链接:点击打开链接

题意:给一个完全图,每个点有一个权值,求一棵生成树,你可以使其中一条边的权值变成0,求该边两点的权值和除以生成树的边权和的最小值

代码:

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
const double INF=0x3f3f3f3f;
using namespace std;
double dis[1005],path[1005][1005],G[1005][1005];
int n,x[1005],y[1005],p[1005],pre[1005],vis[1005],used[1005][1005];
double prim(int v){
    int i,j,u;
    double sum,tmp;
    sum=0;
    memset(vis,0,sizeof(vis));
    memset(used,0,sizeof(used));
    memset(path,0,sizeof(path));
    for(i=1;i<=n;i++){
        dis[i]=G[v][i];
        pre[i]=1;
    }
    vis[v]=1;
    for(i=1;i<n;i++){
        u=v;
        tmp=INF;
        for(j=1;j<=n;j++)
        if(dis[j]<tmp&&vis[j]==0){
            tmp=dis[j];
            u=j;
        }
        sum+=tmp;
        vis[u]=1;
        used[u][pre[u]]=used[pre[u]][u]=1;
        for(j=1;j<=n;j++){
        if(vis[j]&&j!=u)                        //求环上的最大值,pre为父节点
        path[u][j]=path[j][u]=max(path[j][pre[u]],dis[u]);
        if(!vis[j]){
            if(dis[j]>G[u][j]){
                dis[j]=G[u][j];
                pre[j]=u;
            }
        }
        }
    }
    return sum;
}
int main(){                                     //因为A的有N*N种可能,因此我们可以使B尽量小
    int i,j,t;                                  //最小生成树去掉一条边后剩的边的权值的和依旧
    double ans,tmp;                             //是最小的,每去掉一条边后,一棵树被分成了两
    scanf("%d",&t);                             //棵树,A/B的最大值也就是A中点权最大的和B中点
    while(t--){                                 //权最大的
       scanf("%d",&n);
       for(i=1;i<=n;i++)
       scanf("%d%d%d",&x[i],&y[i],&p[i]);
       for(i=1;i<=n;i++)
       for(j=1;j<=n;j++)                        //有N*N条边因此不用初始化
       G[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
       tmp=prim(1);
       ans=0;
       for(i=1;i<=n;i++)
       for(j=1;j<=n;j++)
       if(i!=j){
            if(used[i][j])                      //如果在最小生成树上则直接删除
            ans=max(ans,(p[i]+p[j])*1.0/(tmp-G[i][j]));
            else                                //否则则删除当前环的最大值
            ans=max(ans,(p[i]+p[j])*1.0/(tmp-path[i][j]));
       }
       printf("%.2lf\n",ans);
    }
    return 0;
}


 

你可能感兴趣的:(hdu4081)