LuoguP5540:【模板】最小乘积生成树(几何逼近)
题意:给定N点,M边,每条边有两个属性(a,b),现在让你选N-1条边出来,然后使得∑a*∑b最小。N<200,M<1e4;
思路:我们把∑a看成x,∑b看成y,那么一个方案对应一个二维坐标(x,y)。假设我知道了其中两个方案[A,B],那么,如果另外一个方案C更优,则在二维平面上,C至少要满足在A和B的左边。然后[A,C],[C,B]继续下推。 这个有点像凸包的逼近,所以复杂度和凸包上的点数有关,其理论点数是sqrt(lnN)的。所以总的复杂度趋近于NlogN*sqrt(lnN);
#include<bits/stdc++.h>
#define ll long long
#define pii pair<ll,ll>
#define f first
#define ss second
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
struct in{
int u,v;ll a,b,C;
}s[maxn];
bool cmp(in p,in q){ return p.C<q.C;}
int fa[maxn],N,M; ll ans=1LL<<; pii fcy;
int find(int x){
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
pii solve()
{
pii res=make_pair(,);
rep(i,,N) fa[i]=i;
sort(s+,s+M+,cmp);
rep(i,,M) {
if(find(s[i].u)==find(s[i].v)) continue;
fa[find(s[i].u)]=find(s[i].v);
res.f+=s[i].a;
res.ss+=s[i].b;
}
if(res.f*res.ss<ans||(res.f*res.ss==ans&&res.f<fcy.f)) ans=res.f*res.ss,fcy=res;
return res;
}
void MinMul(pii A,pii B)
{
pii C;
rep(i,,M) s[i].C=(B.f-A.f)*s[i].b+(A.ss-B.ss)*s[i].a;
C=solve();
if(1LL*(B.f-A.f)*(C.ss-A.ss)-1LL*(B.ss-A.ss)*(C.f-A.f)>=) return ;
MinMul(A,C);
MinMul(C,B);
}
int main()
{
pii A,B;
scanf("%d%d",&N,&M);
rep(i,,M) {
scanf("%d%d%lld%lld",&s[i].u,&s[i].v,&s[i].a,&s[i].b);
s[i].u++; s[i].v++;
}
rep(i,,M) s[i].C=s[i].a;
A=solve();
rep(i,,M) s[i].C=s[i].b;
B=solve();
MinMul(A,B);
printf("%lld %lld\n",fcy.f,fcy.ss);
return ;
}
LuoguP5540:【模板】最小乘积生成树(几何逼近)的更多相关文章
- bzoj2395[Balkan 2011]Timeismoney最小乘积生成树
所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...
- HDU5697 刷题计划 dp+最小乘积生成树
分析:就是不断递归寻找靠近边界的最优解 学习博客(必须先看这个): 1:http://www.cnblogs.com/autsky-jadek/p/3959446.html 2:http://blog ...
- 【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树
链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...
- 【算法】最小乘积生成树 & 最小乘积匹配 (HNOI2014画框)
今天考试的时候果然题目太难于是我就放弃了……转而学习了一下最小乘积生成树. 最小乘积生成树定义: (摘自网上一篇博文). 我们主要解决的问题就是当k = 2时,如何获得最小的权值乘积.我们注意到一张图 ...
- Luogu5540 最小乘积生成树
Luogu5540 最小乘积生成树 题目链接:洛谷 题目描述:对于一个\(n\)个点\(m\)条边的无向连通图,每条边有两个边权\(a_i,b_i\),求使\((\sum a_i)\times (\s ...
- Bzoj2395: [Balkan 2011]Timeismoney(最小乘积生成树)
问题描述 每条边两个权值 \(x,y\),求一棵 \((\sum x) \times (\sum y)\) 最小的生成树 Sol 把每一棵生成树的权值 \(\sum x\) 和 \(\sum y\) ...
- bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)
题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...
- BZOJ2395 [Balkan 2011]Timeismoney 【最小乘积生成树】
题目链接 BZOJ2395 题意:无向图中每条边有两种权值,定义一个生成树的权值为两种权值各自的和的积 求权值最小的生成树 题解 如果我们将一个生成树的权值看做坐标,那么每一个生成树就对应一个二维平面 ...
- P5540-[BalkanOI2011]timeismoney|最小乘积生成树【最小生成树,凸壳】
正题 题目链接:https://www.luogu.com.cn/problem/P5540 题目大意 给出\(n\)个点\(m\)条边边权是一个二元组\((a_i,b_i)\),求出一棵生成树最小化 ...
随机推荐
- eclipse 设置所有文件编码为UTF-8(最全)
如何修改eclipse工作空间的字符集以及项目的字符集? 第一种方式:修改eclipse的配置文件 打开{ECLIPSE_HOME}/eclipse.ini文件 在最后一行加上属性: -Dfile ...
- SPA框架 Angular、React、Vue
指尖前端重构(React)技术调研分析 摘要:重构前的技术文档调研与分析,包括技术选型为什么选择react,应用过程中的注意事项等. 一.为什么选择React React是当前前端应用最广泛的框架 ...
- LeetCode 28:实现strStr() Implement strStr()
爱写bug(ID:icodebugs) 作者:爱写bug 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needl ...
- maven setting 配置仓库,pom.xml中repository不起作用
问题描述 最近做java项目,需要使用公司自己搭建的maven仓库,但是有些包公司的仓库中没有,导致下载失败. 项目环境 jdk:1.8 maven:3.5 问题原因分析 maven的setting文 ...
- Unity Shader 屏幕后效果——Bloom外发光
Bloom的原理很简单,主要是提取渲染图像中的亮部区域,并对亮部区域进行模糊处理,再与原始图像混合而成. 一般对亮部进行模糊处理的部分采用高斯模糊,关于高斯模糊,详见之前的另一篇博客: https:/ ...
- numpy 数组增加列,增加行的函数:column_stack,row_stack
def fun_ndarray(): a = [[1,2,7], [-6,-2,-3], [-4,-8,-55] ] b = [3,5,6] a = np.array(a) b = np.array( ...
- Clean Code 笔记 之 第二章
你是否真正的会命名 前言 这是我第二次看这本书了(Clean Code)的时候,第一次看的时候是,看到某世界五百强在他们的代码中我竟然看不到一句注释,现在我还记得当时的情景,当我Download 下第 ...
- Java8 新特性 Stream() API
新特性里面为什么要加入流Steam() 集合是Java中使用最多的API,几乎每一个Java程序都会制造和处理集合.集合对于很多程序都是必须的,但是如果一个集合进行,分组,排序,筛选,过滤...这些操 ...
- 利用SQL计算两个地理坐标(经纬度)之间的地表距离
两个地理坐标(经纬度)地表距离计算公式: 公式解释如下: Long1,Lat1表示A点经纬度,Long2,Lat2表示B点经纬度: a=Lat1–Lat2 为两点纬度之差,b=Long1-Long2为 ...
- struts2的使用入门
虽然说Struts2现在已经被SpringMVC框架淘汰了,据说是有很多安全漏洞.但是Struts2作为一个成熟的MVC框架,还是有必要了解一下的,好歹是曾经风光一时的前辈,老祖宗的东西不能丢下,里面 ...