poj 1944 Qin Shi Huang's National Road System(次小生成树)

UVA - 1494点我点我:-)


题目的意思是:n个城市,需要修建一些道路使得任意两个城市联通,还可以修一条魔法道路, 不花钱, 设魔法路连接的城市的人口之和为A, 所有道路总长为B, 求A/B的最大值

也用到了D[i][j]数组。。。不难不难。。。


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>

using namespace std;

#define MAXN (1000+5)

struct node{
    int u, v, dis;
    
    bool operator <(const node &x)const{
        return dis < x.dis;
    }
};

int X[MAXN], Y[MAXN], peo[MAXN], f[MAXN], D[MAXN][MAXN];
vector<node> G[MAXN];
node edges[MAXN*MAXN];
bool vis[MAXN];

void init(){
    for(int i = 0; i < MAXN; i++) G[i].clear(), f[i] = i;
    memset(D, 0, sizeof(D));
}

int calc(int x1, int y1, int x2, int y2){
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}

int find(int x){
    return x == f[x]? x: (f[x] = find(f[x]));
}

void Bspfa(int s){
	memset(vis, 0, sizeof(vis));
	queue<int> q;
	
	q.push(s); D[s][s] = 0; vis[s] = true;
	while(!q.empty()){
		int now = q.front(); q.pop();
		
		for(int i = 0; i < G[now].size(); i++){
			node next = G[now][i];
			int v = G[now][i].v, dis = G[now][i].dis;
			
			if(vis[v]) continue;
			
			D[s][v] = max(D[s][now], dis);
			q.push(v);
			vis[v] = true;
		}
	}
}

int main(){
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
    
    int T;
    scanf("%d", &T);
    
    while(T--){
        init();
        
        int n, m = 0;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d%d%d", &X[i], &Y[i], &peo[i]);
            
            for(int j = 1; j < i; j++) 
                edges[++m] = ((node){i, j, calc(X[i], Y[i], X[j], Y[j])}); 
        }
        sort(edges+1, edges+m+1);
         
        double sum = 0;
        int tot = 0;;
        for(int i = 1; i <= m; i++){
            node now = edges[i];
            int u = now. u, v = now.v, dis = now.dis;
            int x = find(u), y = find(v);
            if(x == y) continue;
            
            f[x] = y;
            G[x].push_back((node){x, y, dis});
            G[y].push_back((node){y, x, dis});
            sum += sqrt((double)dis); tot++;
            
            if(tot >= n-1) break; 
        }
        
        for(int i = 1; i <= n; i++) Bspfa(i);
        
        double ans = 0;
        for(int i = 1; i <= n; i++)
          for(int j = i+1; j <= n; j++) 
            ans = max(ans, (peo[i]+peo[j])*1.0 / (sum-sqrt(D[i][j])));
          
        printf("%.2lf\n", ans);
    }
    
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值