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

1|0正题

题目链接:https://www.luogu.com.cn/problem/P5540


1|1题目大意

给出n个点m条边边权是一个二元组(ai,bi),求出一棵生成树最小化

(eTae)×(eTbe)

的情况下最小化eTae

1n200,1m104


1|2解题思路

这种带乘积的可以维护凸壳,对于一棵生成树T我们视为一个(eTae,eTbi)的点,这样我们打答案一定在下凸壳上。

可以用一种分治求凸壳的方法,我们先找出下凸壳的两个端点(x最小的和y最小的)记为A,B,然后找到一个在AB的连边下面的一个最凸的点C(可以视为最大化SACB,这样C一定在凸壳上),然后分治下去做ACCB

考虑怎么求这个C,就是最大化AC×CB

(xCxA)(yByA)(xBxA)(yCyA)

=xC(yByA)yC(xBxA)+yA(xBxA)xA(yByA)

然后就是相当于最小化xC(yByA)+yC(xAxB),拿这个当边权跑就可以跑出C了。

然后时间复杂度据说是O(mlogmlnn!)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=210,M=1e4+10; struct node{ ll x,y,w,id; }e[M]; struct point{ ll x,y; point(ll xx=0,ll yy=0) {x=xx;y=yy;return;} }ans; ll n,m,x[M],y[M],a[M],b[M],fa[N]; point operator-(point x,point y) {return point(x.x-y.x,x.y-y.y);} ll operator*(point x,point y) {return x.x*y.y-x.y*y.x;} bool cmp(node x,node y) {return (x.w==y.w)?(a[x.id]<a[y.id]):(x.w<y.w);} ll find(ll x) {return (fa[x]==x)?x:(fa[x]=find(fa[x]));} point Kruskal(){ ll cnt=0;point res=0; for(ll i=1;i<=n;i++)fa[i]=i; sort(e+1,e+1+m,cmp); for(ll i=1;i<=m;i++){ ll x=find(e[i].x),y=find(e[i].y); if(x==y)continue; fa[x]=y;cnt++; res.x+=a[e[i].id]; res.y+=b[e[i].id]; if(cnt==n-1)break; } if(res.x*res.y<ans.x*ans.y)ans=res; else if(res.x*res.y==ans.x*ans.y&&res.x<ans.x) ans=res; return res; } void solve(point A,point B){ for(ll i=1;i<=m;i++) e[i]=(node){x[i],y[i],(B.x-A.x)*b[i]+(A.y-B.y)*a[i],i}; point C=Kruskal(); if((C-A)*(B-A)<=0)return; solve(A,C);solve(C,B); } signed main() { scanf("%lld%lld",&n,&m); for(ll i=1;i<=m;i++){ scanf("%lld%lld%lld%lld",&x[i],&y[i],&a[i],&b[i]); x[i]++;y[i]++; } ans.x=ans.y=1e9; for(ll i=1;i<=m;i++)e[i]=(node){x[i],y[i],a[i],i}; point A=Kruskal(); for(ll i=1;i<=m;i++)e[i]=(node){x[i],y[i],b[i],i}; point B=Kruskal(); solve(A,B); printf("%lld %lld\n",ans.x,ans.y); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14447753.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(86)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示