test 9 小p的生成树 (最大生成树+数论)
来源:互联网 发布:怎么查看手机淘宝等级 编辑:程序博客网 时间:2024/05/21 22:25
题解:最大生成树+数论。
因为我们最终是要求 sqrt(sum(a)^2+sum(b)^2)尽可能的大,所以我们肯定不能单独考虑其中一个权值的影响。那么如何将两个影响考虑到一起呢?我们把(ai,bi)看成是有方向的向量,那么最终选取的边的和应该也是一个有方向的向量,假设我们找出该向量的极角,然后求出每个边对于该方向的投影,投影越大说明对该方向的贡献越大,所以我们可以根据a*cos+b*sin的值排序,然后用kruskal计算此方向的贡献。
那么角度有很多肯定不能全部枚举。根据kruskal的流程可知,生成树的形态与各边权值的相对大小有关,与具体权值无关。
我们考虑两条边的边权x1+y1i余x2+y2i (y1!=y2) 当两条边对应复数的投影相等时,方向向量(cos,sin)需要满足:x1*cos+y1*sin=x2*cos+y2*sin,化简后tan=(x1-x2)/(y2-y1) ,然后用atan可以解出其中的一个角,atan+pi可以得到另一个。而当y1=y2,x1!=x2,式子会化简成x1*cos=x2*cos 此时的角度为pi/2,3*pi/2
我们枚举每一对边,计算出两边投影相等时极角的分界点,此时这些分界点会把[-pi/2,3*pi/2)的极角区间分成若干个小区间。由于每条边的投影的大小是关于极角连续变化的,所以在每个小极角区间内,所有边的投影相对大小关系不变。
于是枚举区间,取区间任意方向做最大生成树即可。
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define N 400000using namespace std;double f[N],a[N],b[N],ans;int fa[N],u[N],v[N],n,m,cnt;struct data{int x,y;double v,a,b;}tr[N];int cmp(data a,data b){return a.v>b.v;}int find(int x){if (fa[x]==x) return x;fa[x]=find(fa[x]);return fa[x];}double work(double x){double x1=sin(x); double y1=cos(x);for (int i=1;i<=m;i++) { tr[i].x=u[i]; tr[i].y=v[i]; tr[i].a=a[i]; tr[i].b=b[i]; tr[i].v=y1*a[i]+x1*b[i];}sort(tr+1,tr+m+1,cmp);for (int i=1;i<=n;i++) fa[i]=i;double ansa=0,ansb=0; int size=0;for (int i=1;i<=m;i++) { int r1=find(tr[i].x); int r2=find(tr[i].y); if (r1!=r2) { fa[r2]=r1; size++; ansa+=tr[i].a; ansb+=tr[i].b; if (size==n-1) break; } }return ansa*ansa+ansb*ansb;}void solve(){cnt=0; ans=-1;for (int i=1;i<=m-1;i++) for (int j=i+1;j<=m;j++) { if (b[i]==b[j]) { f[++cnt]=M_PI/2; f[++cnt]=-M_PI/2; }else f[++cnt]=atan((a[i]-a[j])/(b[j]-b[i])),f[cnt+1]=f[cnt]+M_PI,cnt++; }f[++cnt]=-M_PI/2; f[++cnt]=M_PI*5/2;sort(f+1,f+cnt+1);cnt=unique(f+1,f+cnt+1)-f-1;for (int i=1;i<=cnt;i++) ans=max(ans,work((f[i]+f[i-1])/2));printf("%.6lf\n",sqrt(ans));}int main(){freopen("mst.in","r",stdin);scanf("%d%d",&n,&m);for (int i=1;i<=m;i++) scanf("%d%d%lf%lf",&u[i],&v[i],&a[i],&b[i]);solve();}
0 0
- test 9 小p的生成树 (最大生成树+数论)
- POJ3723最大(或者小)生成树,构建军队,不错的题目
- aoj2224(最大生成树)
- 最大生成树
- poj1797最大生成树
- hdu3367(最大生成树)
- poj1797最大生成树
- poj3273 最大生成树
- 最大生成树
- POJ2377(最大生成树)
- poj3723(最大生成树)
- 最大生成树Kruskal
- Aizu2224 最大生成树??
- 最大生成树 Keroskal
- 最大生成树
- 最大生成树
- poj 2377 最大生成树 最小生成树的变形
- LightOJ - 1029 Civil and Evil Engineer(最大/小生成树)
- 截止总结前新学到的还需要巩固的知识
- leetCode练习(105)
- 在线广告产品实践
- vector 和list的基本使用方法
- 【安卓学习之常见问题】 Listview的setOnItemLongClickListener无法进入问题
- test 9 小p的生成树 (最大生成树+数论)
- Android中Service的生命周期
- 关于线程ID的一些理解
- Activity启动流程
- SSH整合-问题记录
- hdu 1016Prime Ring Problem dfs经典题 素数环
- Android开发中的原生代码的网络访问和请求
- echarts(国产)基于html5-canvas的开源图表绘制组件
- ListView的优化