• 题意
    • n座城市,每座城市有一个坐标(x,y),以及一个人口值(z),任意两个城市之间可以修路,距离为两个城市之间的欧几里得距离
    • 我们可以使得一条路花费为0,前提是两个城市人口之和(A)与其他所有建造的道路和(B)的比值最大
    • 求可以使得任意两个城市可以连通的最小花费(双向边)
  • 题解
    • 一开始以为是一道最优比率生成树
    • 但是发现A仅仅是两个城市人口之和,不能带入0/1规划模型
    • 考虑这样一个做法:每次枚举一条边(u,v),只要能O(1)时间内计算出“在原图中删除边(u,v)后的最小生成树权值”,那么就能在O(n^2)之内计算出答案
    • 只要按照类似次小生成树的做法,先生成一颗原图的最小生成树,然后过程中预处理出maxcost数组,然后枚举边(u,v)之后删除最小生成树中u和v唯一路径上的最大权maxcost[u][v]  (最小瓶颈路的最大边长)
  • 代码
    • 
      
      #include<iostream>
      #include<cstdio>
      #include<set>
      #include<vector>
      #include<algorithm>
      #include<stack>
      #include<queue>
      #include<cmath>
      #include<string>
      #include<cstring>
      #include<cstdlib>
      #include
      <map>
      using namespace std;
      #define scan(n) scanf("%d",&n)
      #define ll long long
      const ll mod = 10007;
      const int maxn = 1e6+10;
      const int INF=0x3f3f3f3f;
      double cost[1010][1010],lowc[2010],ans;
      int n,m;
      bool vis[3010];
      double Max[1010][1010];
      int pre[2020];
      bool used[1010][1010];
      
      double prim(){
          double ans = 0;
          memset(vis,false,sizeof(vis));
          memset(Max,0,sizeof(Max));
          memset(used,0,sizeof(used));
          vis[0]=true;
          pre[0]=-1;
          for(int i=1;i<n;i++){
              lowc[i]=cost[0][i];
              pre[i]=0;
          }
          lowc[0]=0.0;
          for(int i=1;i<n;i++){
              double minc = INF;
              int p=-1;
              for(int j=0;j<n;j++){ if(!vis[j]&&minc>lowc[j]){
                      minc=lowc[j];
                      p=j;
                  }
              }
              if(minc==INF)return -1;
              ans += minc;
              vis[p]=true;
              used[p][pre[p]]=used[pre[p]][p]=true;
              for(int j=0;j<n;j++){ if(vis[j] && j!=p)Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]); if(!vis[j] && lowc[j]>cost[p][j]){
                      lowc[j] = cost[p][j];
                      pre[j]=p;
                  }
              }
          }
          cout<<ans<<endl;
          return ans;
      }
      double x[2010],y[2010],z[2010];
      
      int main(){
          int t;
          scanf("%d", &t);
          while(t--){
              scanf("%d", &n);
              for(int i=0;i<n;i++){
                  scanf("%lf%lf%lf", &x[i],&y[i],&z[i]);
              }
              for(int i=0;i<n;i++){
                  for(int j=i+1;j<n;j++){
                      cost[i][j] = cost[j][i] = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                  }
              }
              double ans1 = prim();
              double maxx=0.0;
              for(int i=0;i<n;i++){
                  for(int j=i+1;j<n;j++){
                      maxx = max(maxx,(z[i]+z[j])/(ans1-Max[i][j]));
                  }
              }
              printf("%.2f\n", maxx);
          }
      
          return 0;
      }

发表评论

邮箱地址不会被公开。 必填项已用*标注