• HDU 4081(最小生成树


    题意:给出一个图,每个顶点有一个权值,要求求出一个生成树,这个树上的某一边长变为0,求该边两端点权值之和与总边权的最大比值。

    思路:枚举权值为0的边,如过该边在最小生成树上,直接减去边权,如果不在树上,添加边必然产生环,此时最小总边权可以通过减去这个环上的最大边权求得。先用prim算法计算最小生成树,计算的时候已经在树上的点和正在添加的点之间路径上的最大边权就是添加的这条边或者和它连边的那个点对应的最大边权。求出所有最大边权之后枚举加边即可。

    #include<bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.0000000001
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=1005;
    int T;
    int n;
    int po[maxv],X[maxv],Y[maxv];
    double G[maxv][maxv];
    double maxlen[maxv][maxv];
    bool used[maxv];
    bool eused[maxv][maxv];
    double mincost[maxv];
    int mincostfrom[maxv];
    double prim(){
        memset(used,0,sizeof used);
        memset(maxlen,0,sizeof maxlen);
        memset(eused,0,sizeof eused);
        for(int i=0;i<maxv;i++){
            maxlen[i][i]=0;
        }
        double ans=0;
        mincostfrom[0]=0;
        for(int i=0;i<=n;i++) mincost[i]=1e20;
        mincost[0]=0;
        int added=0;
        while(added<n){
            double cost=1e8;
            int from,to;
            for(int i=0;i<n;i++){
                if(!used[i]&&mincost[i]<cost){
                    from=mincostfrom[i];
                    cost=mincost[i];
                    to=i;
                }
            }
            eused[from][to]=eused[to][from]=1;
            added++;
            ans+=cost;
            used[to]=1;
            for(int i=0;i<n;i++){
                if(used[i]&&to!=i)
                maxlen[to][i]=maxlen[i][to]=max(maxlen[i][from],max(maxlen[to][i],cost));
            }
            for(int i=0;i<n;i++){
                if(!used[i]&&G[to][i]<mincost[i]){
                    mincostfrom[i]=to;
                    mincost[i]=G[to][i];
                }
            }
        }
        return ans;
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>T;
        while(T--){
            cin>>n;
            for(int i=0;i<n;i++){
                scanf("%d%d%d",X+i,Y+i,po+i);
            }
            for(int i=0;i<n;i++){
                for(int j=i+1;j<n;j++){
                    double dis=sqrt((double)sq(X[i]-X[j])+sq(Y[i]-Y[j]));
                    G[i][j]=G[j][i]=dis;
                }
            }
            double mst=prim();
            double ans=0;
            for(int i=0;i<n;i++){
                for(int j=i+1;j<n;j++){
                    double popu=po[i]+po[j];
                    double tollen;
                    if(eused[i][j]){
                        tollen=mst-G[i][j];
                    }
                    else tollen=mst-maxlen[i][j];
                    ans=max(ans,popu/tollen);
                }
            }
            printf("%.2f
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    OpenFileDialog 类的ShowDialog() 错误的解决
    DataTable.Select()使用心得
    postgis 自相交数据检测 修复
    postgresql 添加列主键自增
    postgresql 死锁处理
    linux 安装中文字体(生成图片中文乱码解决)
    Dockerfile 部署jar
    SpringBoot学习总结文章
    怎样在Linux服务器上部署自己的项目?(超详细)
    关于连接Redis时Could not get a resource from the pool问题
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4675553.html
Copyright © 2020-2023  润新知