zoukankan      html  css  js  c++  java
  • UVALive-5713 Qin Shi Huang's National Road System (次小生成树)

    题目大意:有n个城市,要修一些路使得任意两个城市都能连通。但是有人答应可以不计成本的帮你修一条路,为了使成本最低,你要慎重选择修哪一条路。假设其余的道路长度为B,那条别人帮忙修的道路两端城市中的总人口为B,要找一个使A/B最大的方案。

    题目分析:先求最小生成树,处理出MST中任意两点之间的最长边。因为别人只答应给修一条路,所以枚举这条路,用这条路替换下一条MST中最长的边(在加入这条路后构成的环中),比较求得A/B的最大值。实际上是把求次小生成树的一些后续操作改改。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define REP(i,s,n)  for(int i=s;i<(n);++i)
    
    const int N=1005;
    const double inf=1e30;
    struct Edge
    {
        int to,nxt;
    };
    Edge e[2*N];
    double mp[N][N],dp[N][N],d[N];
    int cnt,n,head[N],x[N],y[N],pl[N],pre[N],vis[N];
    
    void read()
    {
        scanf("%d",&n);
        REP(i,0,n)  scanf("%d%d%d",x+i,y+i,pl+i);
    }
    
    double dist(int xa,int ya,int xb,int yb)
    {
        return sqrt((xa-xb)*(xa-xb)*1.0+(ya-yb)*(ya-yb)*1.0);
    }
    
    void init()
    {
        cnt=0;
        memset(head,-1,sizeof(head));
        REP(i,0,n) REP(j,i+1,n)
            mp[j][i]=mp[i][j]=dist(x[i],y[i],x[j],y[j]);
    }
    
    void add(int u,int v)
    {
        e[cnt].to=v;
        e[cnt].nxt=head[u];
        head[u]=cnt++;
    }
    
    double prim()
    {
        REP(i,0,n){d[i]=mp[0][i],pre[i]=-1,vis[i]=0;}
        double res=0.0;
        REP(k,0,n){
            double minn=inf;
            int f=0;
            REP(i,0,n){
                if(vis[i])  continue;
                if(minn>d[i]){
                    minn=d[i];
                    f=i;
                }
            }
            vis[f]=1;
            res+=d[f];
            REP(i,0,n)  if(!vis[i]&&d[i]>mp[f][i]){
                d[i]=mp[f][i];
                pre[i]=f;
            }
        }
        REP(i,0,n)  if(pre[i]!=-1)
            add(pre[i],i),add(i,pre[i]);
        return res;
    }
    
    void dfs(int fr,int to,double v)
    {
        vis[to]=1;
        dp[fr][to]=v;
        for(int i=head[to];i!=-1;i=e[i].nxt){
            if(!vis[e[i].to])
                dfs(fr,e[i].to,max(v,mp[to][e[i].to]));
        }
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            read();
            init();
            double MST=prim();
            memset(vis,0,sizeof(vis));
            REP(i,0,n){
                memset(vis,0,sizeof(vis));
                dfs(i,i,0);
            }
            double ans=0.0;
            REP(i,0,n) REP(j,i+1,n){
                double B=MST-dp[i][j];
                double A=pl[i]+pl[j];
                ans=max(ans,A/B);
            }
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    散列函数之单散列算法
    NET 使用 RabbitMQ
    leetCode
    Swift 1
    C#并发集合
    多进程与多线程1
    开发编译器
    APUE1
    微服务架构
    ExceptionHandlerMiddleware中间件如何呈现“定制化错误页面”
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4911416.html
Copyright © 2011-2022 走看看