【BZOJ2395】[Balkan 2011]Timeismoney
【BZOJ2395】[Balkan 2011]Timeismoney
题面
题解
如果我们只有一个条件要满足的话直接最小生成树就可以了,但是现在我们有两维啊。。。
我们将每个方法的费用和时间看作一个二维坐标\((x,y)\)
则我们要求\(x\centerdot y=k\)最小即要求反比例函数\(y=\frac kx\)的图像离坐标轴最近。
那么我们怎么求呢?分下面三步:
- \(Step1\)
分别求出离\(y,x\)轴最近的点,这个通过直接最小生成树一维排序可以求出。
- \(Step2\)
现在我们的情况是这样的:

\(A\),\(B\)是我们刚才固定的,现在我们需要找到一个点\(C\),使\(C\)在\(AB\)左侧且离\(AB\)最远。
这个怎么办呢?
其实就是让\(S_{\triangle ABC}\)的面积最大。
因为有
\vec {AC}=(C.x-A.x,C.y-A.y)
\]
且有\(S_{\triangle ABC}=\frac {\vec{AB}*\vec{AC}}2\)(但是这个面积是有向的且为负,所以要使这两个向量乘起来最小)
所以我们要最小化:
=(B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x)\\
=(B.x-A.x)*C.y+(A.y-B.y)*C.x+...
\]
因为我懒后面部分是常数,所以省略了。
那么我直接将改边权为\((B.x-A.x)y[i]+(A.y-B.y)x[i]\),做最小生成树即可。
- \(Step3\)
现在找到了\(C\),递归处理\((A,C)\)、\((C,B)\)即可。
终止条件\(\vec {BA} * \vec{CA}\geq0\),说明此时\(C\)已经跑到\(AB\)右侧去了。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX_N = 205;
const int MAX_M = 1e4 + 5;
struct Point { int x, y; } ;
Point ans = {(int)1e9, (int)1e9};
Point operator - (const Point &l, const Point &r) { return (Point){l.x - r.x, l.y - r.y}; }
int cross(const Point &l, const Point &r) { return l.x * r.y - l.y * r.x; }
int N, M, pa[MAX_N], rnk[MAX_N];
int getf(int x) { return pa[x] == x ? x : pa[x] = getf(pa[x]); }
inline void unite(int x, int y) {
x = getf(x), y = getf(y);
if (rnk[x] == rnk[y]) pa[x] = y, ++rnk[y];
else (rnk[x] < rnk[y]) ? (pa[x] = y) : (pa[y] = x);
}
struct Edge { int u, v, c, t, w; } e[MAX_M];
inline bool operator < (const Edge &l, const Edge &r) { return l.w < r.w; }
#define RG register
inline Point kruskal() {
Point res = (Point){0, 0};
int tot = 0;
for (RG int i = 1; i <= N; ++i) pa[i] = i, rnk[i] = 1;
sort(&e[1], &e[M + 1]);
for (RG int i = 1; i <= M; ++i) {
int u = getf(e[i].u), v = getf(e[i].v);
if (u != v) unite(u, v), res.x += e[i].c, res.y += e[i].t, ++tot;
if (tot == N - 1) break;
}
long long Ans = 1ll * ans.x * ans.y, now = 1ll * res.x * res.y;
if (Ans > now || (Ans == now && res.x < ans.x)) ans = res;
return res;
}
void Div(const Point &A, const Point &B) {
for (RG int i = 1; i <= M; ++i) e[i].w = e[i].t * (B.x - A.x) + e[i].c * (A.y - B.y);
Point C = kruskal();
if (cross(B - A, C - A) >= 0) return ;
Div(A, C); Div(C, B);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
scanf("%d%d", &N, &M);
for (RG int i = 1; i <= M; i++) scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].c, &e[i].t);
for (RG int i = 1; i <= M; i++) ++e[i].u, ++e[i].v, e[i].w = e[i].c;
Point A = kruskal();
for (RG int i = 1; i <= M; i++) e[i].w = e[i].t;
Point B = kruskal();
Div(A, B);
printf("%d %d\n", ans.x, ans.y);
return 0;
}
为什么标签有个凸包呢?因为你满足要求的决策点肯定在凸包上啊
【BZOJ2395】[Balkan 2011]Timeismoney的更多相关文章
- BZOJ2395:[Balkan 2011]Timeismoney——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2395 有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市 ...
- bzoj2395: [Balkan 2011]Timeismoney
Description 有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市能够连通,一条边需要的c的费用和t的时间,定义一个方案的权值v=n-1条边 ...
- BZOJ 2395 [Balkan 2011]Timeismoney(最小乘积生成树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2395 [题目大意] 给出一张无向图,每条边上有a,b两个值,求生成树, 使得suma* ...
- 【最小乘积生成树】bzoj2395[Balkan 2011]Timeismoney
设每个点有x,y两个权值,求一棵生成树,使得sigma(x[i])*sigma(y[i])最小. 设每棵生成树为坐标系上的一个点,sigma(x[i])为横坐标,sigma(y[i])为纵坐标.则问题 ...
- 【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树
链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...
- BZOJ2395 [Balkan 2011]Timeismoney 【最小乘积生成树】
题目链接 BZOJ2395 题意:无向图中每条边有两种权值,定义一个生成树的权值为两种权值各自的和的积 求权值最小的生成树 题解 如果我们将一个生成树的权值看做坐标,那么每一个生成树就对应一个二维平面 ...
- 【BZOJ】2395: [Balkan 2011]Timeismoney
题解 最小乘积生成树! 我们把,x的总和和y的总和作为x坐标和y左边,画在坐标系上 我们选择两个初始点,一个是最靠近y轴的A,也就是x总和最小,一个是最靠近x轴的B,也就是y总和最小 连接两条直线,在 ...
- bzoj 2395: [Balkan 2011]Timeismoney【计算几何+最小生成树】
妙啊,是一个逼近(?)的做法 把两个值最为平面上的点坐标,然后答案也是一个点. 首先求出可能是答案的点xy分别是按照c和t排序做最小生成树的答案,然后考虑比这两个点的答案小的答案,一定在xy连线靠近原 ...
- bzoj2395[Balkan 2011]Timeismoney最小乘积生成树
所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...
随机推荐
- Pygame碰撞检测
学习自小甲鱼视频教学(笔记) 功能实现: 在随机位置生成若干个小球以随机速度运动: 若小球运动出左边界则从右边界进入,上下边界同理: 若两小球相碰撞则都以相反速度运动分开. 代码如下: 1.尝试自己写 ...
- cocos2d-x3.0 后配置信息重置
原文地址:http://blog.csdn.net/qqmcy/article/details/37722689 近期遇到这种一个问题,cocos设置setup.py中ndk.sdk.ant时设置的路 ...
- php memcache分布式和要注意的问题
Memcache的分布式介绍 memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能.服务器端仅包括内存存储功能,其实现非常简单.至于memcached的分布式,则是完全由客户 ...
- selenium + python自动化测试unittest框架学习(二)
1.unittest单元测试框架文件结构 unittest是python单元测试框架之一,unittest测试框架的主要文件结构: File >report >all_case.py &g ...
- MYSQL统计
今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW ...
- iOS 关闭图片渲染
在为Button 设置背景图片的时候, 会发现显示的效果和UI给的图片不一样, 往往是把图片显示成为蓝色, 这是因为在新版的iOS中, 会自动对图片渲染. 我们只要把图片渲染关掉就OK了 - (UII ...
- DataFrame 加减乘除
headlist = ['a', 'b'] datalist = [[1, 2], [0,3], [3,2]] df = pd.DataFrame(data=datalist,columns=head ...
- PDO介绍(16)
安装PDO PDO的数据选项 链接到数据库服务器并选择数据库 错误处理 获取和设置属性 查询执行 准备语句介绍 获取数据 设置绑定列 处理事务
- 京东7Fresh新零售架构设计分析
7Fresh是京东第一个线上线下融合落地的零售创新业务模式,店内有大量设备的集成,设备供应商达50多家,针对线下业务的特点,团队独立规划和设计POS收银系统.店内生产系统.加工系统.货架陈列系统.魔镜 ...
- 协议类接口 - NAND
一.引脚的含义 先看下nand flash是怎么接的,如下所示便为某一款nand存储芯片的引脚图.发现其连地址信号都没有.那么是如何访问地址数据的呢? 查阅该nand flash的数据手册可得其各个引 ...