当前位置: 首页 > news >正文

最优比例生成树(0/1分数规划)

首先这是要解决什么问题:一个带权完全图,每条边都有自己的花费值cost[i]和收益值benifit[i],如果用x[i]来代表一条边取或不取,那么求一个生成树。要求:r=(∑cost[i]*x[i] ) / (∑benifit[i]*x[i] )最小。

经典题目:POJ2728 - Desert King

如何来求解:这里用到了0-1分数规划思想,对于上式可以变形为 z(r)=∑cost[i]*x[i] -r*∑benifit[i]*x[i]。而z(r)=0为我们所求。

这里有个非常重要的结论:z(r)为单调递减函数,因此是线性的。于是"我们可以兴高采烈地把z(r)看做以 cost[i]-r*benifit[i] 为边权的最小生成树的总权值"。显然,我们所求即为z(max(r))=0。这里max(r)是由z=0确定的。

于是有了两种算法:

1、Dinkelbanch算法,即迭代法。取r的一个初值,一般为0,得到一个生成树之后,令r=(∑benifit[i]*x[i] ) / (∑cost[i]*x[i] ),哐哐迭代之后……r是趋于最大值的,而z趋于0。

2、二分法,z(r)=0是我们所求,而它又是单调函数,那么二分r即可。据说二分比迭代慢了很多。

 

 

模板Dinkelbach POJ 2728:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <map>
#include <sstream>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   x < y ? x : y
#define Max(x, y)   x < y ? y : x
#define E(x)    (1 << (x))

const double eps = 1e-6;
typedef long long LL;
using namespace std;

const int N = 1<<10;
const int inf = ~0u>>2;

struct node {
    int x, y, z;
} point[N];

double cost[N][N];
double benifit[N][N];
double mi[N];
int pre[N];
bool vis[N];
double c, d;
int n;

double prim(double ans) {
    int i, j, f;
    double mx;
    c = d = 0;
    for(i = 1; i < n; ++i) {
        mi[i] = cost[0][i] - ans*benifit[0][i];
        pre[i] = 0;
        vis[i] = false;
    }
    mi[0] = 0;
    vis[0] = true;
    for(i = 0; i < n - 1; ++i) {
        mx = inf; f = 0;
        for(j = 0; j < n; ++j) {
            if(!vis[j] && mx > mi[j]) {
                mx = mi[j];
                f = j;
            }
        }
        c += cost[pre[f]][f];
        d += benifit[pre[f]][f];
        vis[f] = true;

        for(j = 1; j < n; ++j) {
            double val = cost[f][j] - ans*benifit[f][j];
            if(!vis[j] && mi[j] > val) {
                pre[j] = f;
                mi[j] = val;
            }
        }
    }
    return c/d;
}

int iabs(int x) {
    return x < 0 ? -x : x;
}

void init() {
    int i, j;
    for(i = 0; i < n; ++i) {
        for(j = 0; j < n; ++j) {
            cost[i][j] = iabs(point[i].z - point[j].z);
            benifit[i][j] = sqrt(1.*(point[i].x - point[j].x)*(point[i].x - point[j].x) +
                                 1.*(point[i].y - point[j].y)*(point[i].y - point[j].y));
        }
    }
}

void solve() {
    double ans = 0, tmp;
    while(1) {
        tmp = prim(ans);
        if(fabs(ans - tmp) < eps)   break;
        else    ans = tmp;
    }
    printf("%.3f\n", ans);
}

int main() {
    freopen("data.in", "r", stdin);

    int i;
    while(scanf("%d", &n), n) {
        for(i = 0; i < n; ++i) {
            scanf("%d%d%d", &point[i].x, &point[i].y, &point[i].z);
        }
        init();
        solve();
    }
    return 0;
}

相关文章:

  • KVM安装与使用
  • Windows8手机有截图功能?
  • 迪普科技为上海银视通打造“下一代”数据中心
  • 【热门精品】2012年iOS开发人员必看的精品资料(100个)
  • 理解管理信息系统
  • 程序即人生 » 移动平台现在可用的C++ 11特性
  • 微信诈骗产业链,俩字儿是核心:杀熟
  • 输出IOS 版本号
  • 新连接?新商业 一场关于商业变革的活动正在进行
  • python伪造HTTP-REFERER
  • 东软启动UniEAP SaCa全国巡展 并联合IDC发布业务基础平台白皮书
  • NewLife.XCode 上手指南
  • 【C++】不同含义new和delete
  • oracle非空约束
  • PHP版冒泡排序法
  • input的行数自动增减
  • java2019面试题北京
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 阿里云Kubernetes容器服务上体验Knative
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 诡异!React stopPropagation失灵
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 使用Gradle第一次构建Java程序
  • 小程序01:wepy框架整合iview webapp UI
  • elasticsearch-head插件安装
  • #Linux(Source Insight安装及工程建立)
  • #Z0458. 树的中心2
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (solr系列:一)使用tomcat部署solr服务
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (七)c52学习之旅-中断
  • (三) diretfbrc详解
  • (一)WLAN定义和基本架构转
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)Scala的“=”符号简介
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .md即markdown文件的基本常用编写语法
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .net mvc部分视图
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 动态调用WebService + WSE + UsernameToken
  • .net 使用ajax控件后如何调用前端脚本
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET开源快速、强大、免费的电子表格组件
  • .NET中的十进制浮点类型,徐汇区网站设计
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @property括号内属性讲解
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...