• 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
  • 相关阅读:
    选择排序法
    计算大阶乘(值很大)
    递归计算阶乘
    计算m的m次方倒数的和
    使用文件(FILE)输入输出
    判断回文数
    最小公倍数(调用函数与全局变量)
    How to 共用体
    How to 枚举
    有效编写软件的75条建议(转)
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4675553.html
Copyright © 2020-2023  润新知