题意

每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小

题解

为什么生成树会和计算几何扯上关系……

对于每棵树,设\(x=c,y=t\),我们可以把它看成平面上的一个点,其中\(\sum c\)为横坐标,\(\sum t\)为纵坐标。那么题目就可以转化成求反比例函数图像上的点\(k=xy\)满足\(k\)最小

我们先求出一棵\(\sum c\)最小的生成树,设这个点为\(A\),和一棵\(\sum t\)最小的生成树,设为\(B\),那么如果一个点\(C\)它们更优它肯定在直线\(AB\)的下方

证明:因为\(C\)比\(A,B\)更优,所以\(A,B\)肯定在这个反比例函数图像的上方。如果点\(A\)不在直线下方,画个图就会发现它必定有纵坐标小于\(B\)或者横坐标小于\(A\),与\(A,B\)的定义矛盾。故如果该点存在必定在直线\(AB\)下方

那么我们需要寻找一个在直线\(AB\)下方且离这条直线最远的一个点\(C\)来更新答案,也就是说要满足\(AB\)叉乘\(AC\)最小,即最小化

\[\begin{aligned}
Ans
&=(B.x-A.x)(C.y-A.y)-(C.x-A.x)(B.y-A.y)\\
&=C.y(B.x-A.x)-C.x(B.y-A.y)-A.y(B.x-A.x)+A.x(B.y-A.y)\\
\end{aligned}
\]

后面两项是常数不用考虑,那么就是要最小化\(C.y(B.x-A.x)-C.x(B.y-A.y)\)。我们把每条边的权值设为\(y(B.x-A.x)-x(B.y-A.y)\),跑一遍最小生成树就能得到\(C\)了。之后再对\((A,C),(C,B)\)递归下去即可

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define inf 1e18
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=205,M=10005;
struct eg{
int u,v,c,t,w;
inline bool operator <(const eg &b)const{return w<b.w;}
inline void rd(){u=read()+1,v=read()+1,c=read(),t=read();}
}e[M];
struct node{
int x,y;
node(){}
node(R int xx,R int yy):x(xx),y(yy){}
inline node operator -(const node &b)const{return node(x-b.x,y-b.y);}
inline ll operator *(const node &b)const{return 1ll*x*b.y-1ll*y*b.x;}
inline bool operator >(const node &b)const{return 1ll*x*y==1ll*b.x*b.y?x>b.x:1ll*x*y>1ll*b.x*b.y;}
}mc,mt,res(inf,inf);
int n,m,u,v,fa[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
node kruskal(){
int tot=0;node P(0,0);
fp(i,1,n)fa[i]=i;
fp(i,1,m){
u=find(e[i].u),v=find(e[i].v);
if(u!=v){
fa[u]=v,++tot;
P.x+=e[i].c,P.y+=e[i].t;
if(tot==n-1)break;
}
}
return cmin(res,P),P;
}
void solve(node A,node B){
fp(i,1,m)e[i].w=1ll*e[i].t*(B.x-A.x)-1ll*e[i].c*(B.y-A.y);
sort(e+1,e+1+m);
node C=kruskal();
if((B-A)*(C-A)>=0)return;
solve(A,C),solve(C,B);
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
fp(i,1,m)e[i].rd();
fp(i,1,m)e[i].w=e[i].c;
sort(e+1,e+1+m),mc=kruskal();
fp(i,1,m)e[i].w=e[i].t;
sort(e+1,e+1+m),mt=kruskal();
solve(mc,mt);
printf("%d %d\n",res.x,res.y);
return 0;
}

bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)的更多相关文章

  1. bzoj2395[Balkan 2011]Timeismoney最小乘积生成树

    所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...

  2. Bzoj2395: [Balkan 2011]Timeismoney(最小乘积生成树)

    问题描述 每条边两个权值 \(x,y\),求一棵 \((\sum x) \times (\sum y)\) 最小的生成树 Sol 把每一棵生成树的权值 \(\sum x\) 和 \(\sum y\) ...

  3. bzoj 2395 [Balkan 2011]Timeismoney——最小乘积生成树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2395 如果把 \( \sum t \) 作为 x 坐标,\( \sum c \) 作为 y ...

  4. 【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树

    链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...

  5. bzoj2395: [Balkan 2011]Timeismoney

    Description      有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市能够连通,一条边需要的c的费用和t的时间,定义一个方案的权值v=n-1条边 ...

  6. BZOJ2395 [Balkan 2011]Timeismoney 【最小乘积生成树】

    题目链接 BZOJ2395 题意:无向图中每条边有两种权值,定义一个生成树的权值为两种权值各自的和的积 求权值最小的生成树 题解 如果我们将一个生成树的权值看做坐标,那么每一个生成树就对应一个二维平面 ...

  7. 【最小乘积生成树】bzoj2395[Balkan 2011]Timeismoney

    设每个点有x,y两个权值,求一棵生成树,使得sigma(x[i])*sigma(y[i])最小. 设每棵生成树为坐标系上的一个点,sigma(x[i])为横坐标,sigma(y[i])为纵坐标.则问题 ...

  8. P5540-[BalkanOI2011]timeismoney|最小乘积生成树【最小生成树,凸壳】

    正题 题目链接:https://www.luogu.com.cn/problem/P5540 题目大意 给出\(n\)个点\(m\)条边边权是一个二元组\((a_i,b_i)\),求出一棵生成树最小化 ...

  9. 洛谷 P5540 - [BalkanOI2011] timeismoney | 最小乘积生成树(最小生成树)

    洛谷题面传送门 大概是一个比较 trivial 的小 trick?学过了就不要忘了哦( 莫名奇妙地想到了 yyq 的"hot tea 不常有,做过了就不能再错过了" 首先看到这种二 ...

随机推荐

  1. babel-preset-latest使用介绍

    本文介绍babel中的babel-preset-latest插件 简介 该插件的作用是包含了每年的js代码转换规则 默认包含es2015,es2016,es2017,默认对这些代码都会进行转码,从而方 ...

  2. matlab 在柱状图上 显示数字

    x = rand(100,1);[n,y] = hist(x);bar(y,n);for i = 1:length(y)text(y(i),n(i)+0.5,num2str(n(i)));end

  3. 201671010140. 2016-2017-2 《Java程序设计》java学习第三周

    java学习第三周       不知不觉,学习java已经是第三周了,不同于初见时的无措,慌张,在接触一段时日后,渐渐熟悉了一些,了解到了它的便利之处,也体会到了它的一些难点,本周主攻第四章,< ...

  4. 使用Java读取XML数据

    ---------------siwuxie095 工程名:TestReadXML 包名:com.siwuxie095.xml 类名:ReadXML.java 打开资源管理器,在工程 TestRead ...

  5. 使用python创建生成动态链接库dll

    如今,随着深度学习的发展,python已经成为了深度学习研究中第一语言.绝大部分的深度学习工具包都有python的版本,很多重要算法都有python版本的实现.为了将这些算法应用到具体工程中,这些工具 ...

  6. WCF4.0 –- RESTful WCF Services

    转自:http://blog.csdn.net/fangxinggood/article/details/6235662 WCF 很好的支持了 REST 的开发, 而 RESTful 的服务通常是架构 ...

  7. HTTP请求:POST和GET的差异

    1,一般情况下应用目的不同:GET是从服务器上获取数据,POST是向服务器传送数据. 2,将数据提交到服务器的方式不同:GET是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各 ...

  8. Django框架 之 Pagination分页实现

    Django框架 之 Pagination分页实现 浏览目录 自定义分页 Django内置分页 一.自定义分页 1.基础版自定义分页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  9. 通过event事件来控制红绿灯通行车辆

    事件的初始值为False,所以最开始就是红灯,先模拟红绿灯的规律,设定为每两秒变换一次灯,然后再模拟车辆通行,通过事件来将两者的事件结合起来, 当事件为False时,为红灯,车辆处于等待状态,一直wa ...

  10. App测试从入门到精通之UI测试

    UI(user interface用户界面)的简称.UI测试也是APP测试中需要考虑的一个层面.用户至上,这个太重要了.一个好的App在界面的UI层设计上应该要满足简洁.美观.大气(这个是自己感觉的哈 ...