zoukankan      html  css  js  c++  java
  • poj2728

    题意:一个无向图,每条边有两个权值,c和l,要求一个生成树,使得所有边的c的和比上l的和最小。

    分析:最优比例生成树。现在要求(c1+...)/(l1+...),设一个比例值变量为r。令r>=(c1+...)/(l1+...)。现在题目转化为求r的最小值。

    假设我们对于一个确定的r可以判断该不等式是否可以满足,那么我们可以用二分查找的方法来求r的最小值,因为r猜大了则可满足,猜小了则不可满足。

    然而,我们确实可以对于一个确定的r来判定是否可满足不等式,方法如下:

    现在r是确定的,相当于已知r。先将不等式整理为如下形式:(r*l1-c1)+...>=0,然后我们使不等式左边尽量大即可。现在不等式左边的的每个括号里都只与一个边有关,把这个括号里的值作为这个边的权值,求图的最大生成树即可使得左边最大。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    #include
    <cmath>
    usingnamespace std;

    #define maxn 1005
    #define eps 0.0001
    #define inf 1000000000

    struct Village
    {
    int x, y, z;
    } village[maxn];

    double dist[maxn][maxn], map[maxn][maxn], mindist[maxn];
    int height[maxn][maxn], n;
    bool vis[maxn];

    double getdist(const Village &a, const Village &b)
    {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }

    void input()
    {
    for (int i =0; i < n; i++)
    scanf(
    "%d%d%d", &village[i].x, &village[i].y, &village[i].z);
    for (int i =0; i < n; i++)
    for (int j = i +1; j < n; j++)
    {
    dist[i][j]
    = dist[j][i] = getdist(village[i], village[j]);
    height[i][j]
    = height[j][i] = abs(village[i].z - village[j].z);
    }
    }

    void makemap(double mid)
    {
    for (int i =0; i < n; i++)
    for (int j = i +1; j < n; j++)
    map[j][i]
    = map[i][j] =- mid * dist[i][j] + height[i][j];
    }

    double prim(double dist[])
    {
    double ans =0;
    for (int i =0; i < n; i++)
    dist[i]
    = inf;
    memset(vis,
    0, sizeof(vis));
    dist[
    0] =0;
    while (1)
    {
    double mindist = inf;
    int mini =-1;
    for (int i =0; i < n; i++)
    if (dist[i] < mindist &&!vis[i])
    {
    mindist
    = dist[i];
    mini
    = i;
    }
    if (mini ==-1)
    return ans;
    vis[mini]
    =true;
    ans
    += mindist;
    for (int i =0; i < n; i++)
    if (!vis[i] && map[mini][i] < dist[i])
    dist[i]
    = map[mini][i];
    }
    }

    double binarysearch()
    {
    double l =0, r =1000000000;
    while (r - l > eps)
    {
    double mid = (l + r) /2;
    makemap(mid);
    double temp = prim(mindist);
    if (temp >=0)
    l
    = mid;
    else
    r
    = mid;
    }
    return l;
    }

    int main()
    {
    //freopen("D:\\t.txt", "r", stdin);
    while (scanf("%d", &n) != EOF && n !=0)
    {
    input();
    printf(
    "%.3f\n", binarysearch());
    }
    return0;
    }
  • 相关阅读:
    练习
    js简介、基本语法、类型转换、变量、运算符、分支语句、循环语句、函数、函数调用
    样式表、格式布局、流式布局
    表单
    图片热点、网页划区
    JS模拟窗口
    JavaScript 常用功能实现一览(一)
    分页打印控制 摘自于网络:http://www.cnblogs.com/joinger/articles/1807517.html
    我眼中的C#3.0 摘自于网络:http://www.cnblogs.com/joinger/articles/1297237.html
    .net ToString()用法详解与格式说明
  • 原文地址:https://www.cnblogs.com/rainydays/p/1993091.html
Copyright © 2011-2022 走看看