链接:

#include <stdio.h>
int main()
{
puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢");
puts("网址:blog.csdn.net/vmurder/article/details/46828379");
}

题解:

裸最小乘积生成树。

最小乘积生成树定义:

有一张n个点m条边的无向图,每条边有k个权值。

如今要取一个边集M使得其将全部点连通。并使

∏ki=1(∑j∈Mjcost(j,vali)) 最小

即个边集的每一种边权的总和的乘积最小。

比方:

k=1时,就是裸最小生成树。

k=2时。就是要使 [边集的权值1的和]*[边集的权值2的和] 最小。

最小乘积生成树的一种求法:

广义上的说法(不是必需看,或者看完以下的再来看这个就好)

首先我们能够把每种生成树想成一个k维的点,第i维的坐标即那一维上权值的和。

然后我们能够先求出每一维坐标最小的一棵生成树(裸上最小生成树就好)。

然后得到一个k-1维的面,然后我们来求一下离这个面最远的点,然后分治下去……据说期望非常快……

二维最小乘积生成树的求法:

给每一棵生成树都定义两个权值X、Y,当中X为其包括的全部边的权值x的和,Y为其包括的全部边的权值y的和,那么我们能够把每一种生成树看成一个坐标。

我们先求出坐标x最小的一棵生成树。再求出坐标y最小的一棵生成树。

然后我们能够考虑。最优的点一定在下凸包上【证明一】,然后我们要进行一个不断向左下拓展点的过程:对于两个点A、B形成的直线,我们能够找出在这条直线左下的最远的点C。然后对AC、CB递归做相同的过程,直到找不到一个在左下的点C为止。

然后怎样找一个最远的点C呢?

我们能够发现既然有一条边固定,那么最好还是把“最远”转化成三角形面积最大。这个用叉积搞一搞,,然后会推出公式面积跟点C有关的部分= 常数A∗x+常数B∗y ,,那么我们把全部边的权值 x 乘上 A ,权值 y 乘上 B 就好了,,,A、B 是啥自己求去!

【题外】:三维的,就是离一个平面最远。转化成体积最大。递归分成三层而非两层,。。,。然后四维,甚至更高维,感觉应该是同理的吧?

关于上文中【证明一】

每一个点(xi,yi) 都相应一条函数曲线 ki=xi∗yi,而随意两不同 ki ,它们的函数曲线是不交的(有交的话则存在一点 (xj,yj) 使得 ki=xj∗yj=kj而ki!=kj 成立,显然这是悖论),那么显然最长处肯定不会在凸包内,否则必有凸包上一点比它优。

那么会不会求出这个某种意义上的凸包后,最长处在凸包外,却没被找到呢?

不会。

若有这样的情况。此点必定在凸包上某边的左下方。。然后一定会被找出来。。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 205
#define M 10100
#define inf 0x3f3f3f3f
using namespace std;
struct Eli
{
int u,v,a,b,c;
void read()
{
scanf("%d%d%d%d",&u,&v,&a,&b);
u++,v++;
}
}e[M];
inline bool cmpa(const Eli &a,const Eli &b){return a.a<b.a;}
inline bool cmpb(const Eli &a,const Eli &b){return a.b<b.b;}
inline bool cmpc(const Eli &a,const Eli &b){return a.c<b.c;}
struct Point
{
int x,y;
void print(){printf("%d %d\n",x,y);}
Point(int _x=0,int _y=0):x(_x),y(_y){}
bool operator < (const Point &A)const
{
unsigned int p= x;p*= y;
unsigned int q=A.x;q*=A.y;
return p==q? x<A.x:p<q;
}
}ans,now,mina,minb;
int f[N],n,m;
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
Point Kruscal()
{
int i,fa,fb;
now=Point(0,0);
for(i=1;i<=n;i++)f[i]=i;
for(i=1;i<=m;i++)
{
fa=find(e[i].u),fb=find(e[i].v);
if(fa!=fb)
{
f[fb]=fa;
now.x+=e[i].a;
now.y+=e[i].b;
}
}
if(now<ans)ans=now;
return now;
}
inline int xmul(const Point &A,const Point &B,const Point &C)
{return (C.y-A.y)*(B.x-A.x)-(C.x-A.x)*(B.y-A.y);}
void work(const Point &A,const Point &B)
{
for(int i=1;i<=m;i++)
e[i].c=e[i].b*(A.x-B.x)+e[i].a*(B.y-A.y);
sort(e+1,e+m+1,cmpc);
Point C=Kruscal();
if(xmul(A,B,C)<=0)return ;
work(A,C),work(C,B);
}
int main()
{
// freopen("test.in","r",stdin); int i,j,k;
int a,b,c;
ans=Point(inf,inf); scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)e[i].read();
sort(e+1,e+m+1,cmpa),mina=Kruscal();
sort(e+1,e+m+1,cmpb),minb=Kruscal();
work(minb,mina),ans.print(); fclose(stdin);
fclose(stdout);
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

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

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

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

  6. bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)

    题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...

  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. [置顶] 单例模式lua实现

    --[[ 优点 一.实例控制 单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例. 二.灵活性 因为类控制了实例化过程,所以类可以灵活更改实例化过程. 缺点 一.开销 ...

  2. 微信小程序 - 下拉刷新(非组件)

    详情见示例:refresh

  3. 机器学习-分类器-级联分类器训练(Train CascadeClassifier )

    一.简介: adaboost分类器由级联分类器构成,"级联"是指最终的分类器是由几个简单分类器级联组成.在图像检测中,被检窗口依次通过每一级分类器,这样在前面几层的检测中大部分的候 ...

  4. 如何解析android访问webservice返回的SoapObject数据(可用)

    怎么解析android访问webservice返回的SoapObject数据 本帖最后由 kkDragon123 于 2013-03-26 15:50:07 编辑 我的数据如下:mingdanResp ...

  5. ios网络学习------9 播放网络视频

    IOS提供了叫做MPMoviePlayerController  MPMoviePlayerViewController两个类.能够轻松用来实现视频播放. MPMoviePlayerViewContr ...

  6. Linux下几款C++程序中的内存泄露检查工具

    https://blog.csdn.net/gatieme/article/details/51959654

  7. django之创建第7-5-第二种传值方式(time/1232/xiaodneg)

    1.修改views文件 def foo(request,myID,myName): t = loader.get_template("foo.html") user = {&quo ...

  8. js动态创建HTML(radio、checkbox...)[摘抄]

    function create(parentId,eleType,eleName,eleId,eleValue){ var board = document.getElementById(parent ...

  9. nfs远程挂载问题记录

    问题描述: mount: wrong fs type, bad option, bad superblock on x.x.x.x:/xxxx_domain/update,missing codepa ...

  10. Qt5中表格处理大数据量

    在Qt中如果是普通项目,GUI处理展现的数据量不大,一般用QTableWidget,QTreeWidget这样的控件就满足了,但是如果数据量行数达到了几万行,那么Widget的展示性能就偏差了. Qt ...