HDU - 4081 Qin Shi Huang's National Road System 次小生成树

HDU - 4081 

题意:

秦始皇要修路,使得这些路的长度和尽量短。徐福有一个可以消掉路长度的技能,只能用一次。问:
假设A=用法术建的那条路的两端的城市的总人口数,B=除了徐福造的那条路以外的路的总长度,建造的路要使得A/B最大。输出A/B。

思路:

既然要总的路最小,就先求一遍最小生成树,消耗为tot。然后枚举路径,如果这个路径在最小生成树上,就用tot减去这个路径的长度得B;
如果这条路径不在生成树上,那么,假如把这个路径加在树上,可得一环,为了使得B尽量小,为了保持树结构,可以消去这个环中最长的路径。
次小生成树就是可以得到树上任意两点间的最长路径段。然后我一直知道prim的思路,但今天才发现这个n*n的方法还挺有用的。
 
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <iostream>
const int inf = 0x3f3f3f3f;
using namespace std;
const int maxn = 1009;
double g[maxn][maxn];
int p[maxn],X[maxn],Y[maxn];
double maxx[maxn][maxn],dis[maxn];
int fa[maxn];
int mark[maxn];
int cnx[maxn][maxn];
int n;
double dt(int i,int j){
    return sqrt((X[i] - X[j]) *(X[i] - X[j])*1.0 + (Y[i] - Y[j]) *(Y[i] - Y[j])*1.0);
}
double prim(){
            double res = 0.0;
            for(int i=1; i<=n; i++)
            {
                    dis[i] = g[1][i];
                    mark[i] = false;    
                    fa[i]  = 1;
            }
            mark[1] = true;     dis[1] = 0.0;

            for(int i=1; i<n; i++){
                int pos = -1;
                double minn = 99999999.9;

                for(int j=1; j<=n; j++){
                    if(!mark[j]&&dis[j] < minn){
                        minn = dis[j];
                        pos = j;
                    }
                }
                if(pos==-1)return res;

                mark[pos] = true;
                int pre = fa[pos];
                res += minn;
                cnx[pre][pos]=1;
                cnx[pos][pre]=1;
                maxx[pos][pre] = maxx[pre][pos] = minn;

                for(int j=1; j<=n; j++){
                    if(!mark[j]||j==pos)continue;
                    maxx[j][pos] = max(maxx[j][pre], maxx[pre][pos]);
                    maxx[pos][j] = maxx[j][pos];
                }

                for(int j=1; j<=n; j++){
                    if(!mark[j] && dis[j] > g[pos][j]){
                        dis[j] = g[pos][j];
                        fa[j] = pos;
                    }
                }
            }

            return res;

}
int main(){
            int t;
            scanf("%d" , & t);
            while(t--){
                
                scanf("%d", &n);
                memset(maxx,0,sizeof(maxx));
                memset(cnx,0,sizeof(cnx));
                for(int i=1; i<=n; i++){
                    scanf("%d%d%d", &X[i], &Y[i], &p[i]);
                    g[i][i] = 0.0;
                    for(int j=1; j<i; j++){
                        g[i][j] = dt(i,j);
                        g[j][i] = g[i][j];
                    }
                }
                
                double tot = prim();
                double ans = 0.0;
                // cout<<"tot"<<tot<<endl;
                for(int i=1; i<=n; i++){
                    for(int j=1; j<=n; j++){
                        if(i==j)continue;
                        if(cnx[i][j])
                            ans = max(ans, 1.0*(p[i] + p[j]) /(tot - g[i][j]));
                        else 
                            ans = max(ans, 1.0*(p[i] + p[j]) / (tot - maxx[i][j]));
                    } 
                }

                printf("%.2lf\n",ans);
            }


    return 0;
}
HDU 4081

 

posted @ 2018-07-17 23:32  ckxkexing  阅读(129)  评论(0编辑  收藏  举报