[CSP-S模拟测试]:小P的生成树(数学+Kruskal)
题目描述
小$P$是个勤于思考的好孩子,自从学习了最大生成树后,他就一直在想:能否将边权范围从实数推广到复数呢?可是马上小$P$就发现了问题,复数之间的大小关系并没有定义。于是对于任意两个复数$z_1,z_2$,小$P$定义$z_1<z_2$当且仅当$|z_1|<|z_2|$。
现在,给出一张$n$个点$m$条边的简单无向带权图,小$P$想问你,如果按照他对复数大小的定义,这个图的最大生成树是什么?
输入格式
输入的第一行为两个正整数$n$和$m$,分别表示这个无向图的点数和边数。
接下来$m$行,每行四个整数$u,v,a,b(1\leqslant u,v\leqslant n,-1000\leqslant a,b\leqslant 1000)$,表示点$u$与点$v$之间有一条无向边,边权为$a+bi$。
输出格式
输出仅有一个实数,它等于所有的最大生成树中所有边权之和的模长。
实数四舍五入,保留六位小数。
样例
样例输入1:
3 3
1 2 1 3
2 3 2 2
3 1 3 1
样例输出1:
5.830952
样例输入2:
6 9
1 2 4 -1
2 3 4 1
3 4 -1 -5
1 5 -4 0
4 6 1 -6
2 6 -6 0
5 6 -7 5
2 4 7 1
1 4 -9 -5
样例输出2:
27.459060
数据范围与提示
样例$1$解释:
显然,从该图三条边中任取两条便可以构成一棵生成树,这三棵生成树的边权之和分别为$z_1=3+5i,z_2=4+4i,z_3=5+3i$,其中$|z_2|=\sqrt{32}<|z_1|=|z_3|=\sqrt{34}$。
数据范围:
对于$10\%$的数据:$n\leqslant 6$
对于$30\%$的数据:$n\leqslant 12$
对于另外$20\%$的数据:每条边的边权均为实数
对于$100\%$的数据:$n\leqslant 50,m\leqslant 200$,给定的无向图至少存在一个生成树
提示:
简单无向图的定义为:没有任何重边和自环的无向图。
若复数$z_1=a_1+b_1i,z_2=a_2+b_2i$,则$z_1+z_2=(a_1+a_2)+(b_1+b_2)i$。
设复数$z=a+bi$,符号$|z|=\sqrt{a^2+b^2}$表示该复数的模长。
若复数$z=a+bi$满足条件$b=0$,则该复数为实数。
题解
假设我们已经知道了生成树中各边求和所得复数的单位方向向量,那么要使得生成树的边权和模长最大,只需各复数在该方向向量上的投影之和最大。于是,我们将每条边对应的复数在该方向向量上的投影作为其新的权值,做一遍最大生成树即可解决。
但是显然我们不能枚举所有的方向向量。
但是根据$kruskal$的算法流程我们可以知道:
生成树的形态只与各边边权的相对大小有关,而与具体权值无关。
不妨设两条边,其边权分别是$x_1+y_1i$和$x_2+y_2i(y_1\neq y_2)$当两条边对应的复数投影相等时,方向向量$(\cos\theta,\sin\theta)$需要满足:$x_1\cos\theta+y_1\sin\theta=x_2\cos\theta+y_2\sin\theta$,化简后得$\tan\frac{x_1-x_2}{y_2-y_1}\Rightarrow\theta 1=\arctan\frac{x_1-x_2}{y_2-y_1},\theta 2=\arctan\frac{x_1-x_2}{y_2-y_1}+\pi$。而当$y_1=y_2,x_1\neq x_2$时,等式化为$x_1\cos\theta=x_2\cos\theta\Rightarrow \cos\theta=0\Rightarrow \theta 1=\frac{\pi}{2},\theta 2=\frac{3\pi}{2}$。
那么,我们可以枚举每一对边,算出两条边投影相等时计较的分解点,此时这些分解点会把$[-\frac{\pi}{2},\frac{3\pi}{2})$的极角分成若干个小区间。由于每条变得投影大小关于极角$\theta$是连续变化的,所以在每个小极角区间内,所有边的投影相对大小关系不变。
于是我们可以对于每个区间任取一个方向向量做最大生成树,最后取最优方案即可。
需要注意的是因为$\arctan$无法求出$\frac{\pi}{2}$和$\frac{3\pi}{2}$,所以要插入这两个值。
时间复杂度:$\Theta(m^3\log m)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
using namespace std;
struct rec{int x,y;double a,b,s;}e[201];
int n,m,cnt;
int fa[51];
double ans,theta[40001];
bool cmp(rec a,rec b){return a.s>b.s;}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
double kruskal(double x)
{
int res=0;
double a=0.0,b=0.0;
for(int i=1;i<=m;i++)e[i].s=e[i].a*sin(x)+e[i].b*cos(x);
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
int x=find(e[i].x),y=find(e[i].y);
if(x==y)continue;
fa[x]=y;
res++;
a+=e[i].a;
b+=e[i].b;
if(res==n-1)break;
}
return a*a+b*b;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%lf%lf",&e[i].x,&e[i].y,&e[i].a,&e[i].b);
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
if(e[i].b==e[j].b)theta[++cnt]=M_PI/2.0;
else{theta[++cnt]=atan((e[i].a-e[j].a)/(e[j].b-e[i].b));theta[++cnt]=theta[cnt-1]+M_PI;}
theta[++cnt]=-M_PI/2.0;
theta[++cnt]=M_PI*3.0/2.0;
sort(theta+1,theta+cnt+1);
cnt=unique(theta+1,theta+cnt+1)-theta-1;
for(int i=1;i<=cnt;i++)ans=max(ans,kruskal(theta[i]));
printf("%.6lf",sqrt(ans));
return 0;
}
rp++
[CSP-S模拟测试]:小P的生成树(数学+Kruskal)的更多相关文章
- [CSP-S模拟测试]:小P的2048(模拟)
题目描述 最近,小$P$迷上了一款叫做$2048$的游戏.这块游戏在一个$n\times n$的棋盘中进行,棋盘的每个格子中可能有一个形如$2^k(k\in N^*)$的数,也可能是空的.游戏规则介绍 ...
- [CSP-S模拟测试]:小L的数(数位DP+模拟)
题目传送门(内部题132) 输入格式 第一行一个整数$t$. 接下来$t$行每行一个整数$n$. 输出格式 $t$行,每行一个整数表示答案. 样例 样例输入: 41818231232691052109 ...
- [CSP-S模拟测试]:小盆友的游戏(数学 or 找规律)
题目传送门(内部题110) 输入格式 第一行一个整数$N$,表示小盆友的个数. 第二行$N$个整数$A_i$,如果$A_i=-1$表示$i$目前是自由身,否则$i$是$A_i$的跟班. 输出格式 一个 ...
- [CSP-S模拟测试]:小P的单调数列(树状数组+DP)
题目描述 小$P$最近喜欢上了单调数列,他觉得单调的数列具有非常多优美的性质.经过小$P$复杂的数学推导,他计算出了一个单调增数列的艺术价值等于该数列中所有书的总和.并且以这个为基础,小$P$还可以求 ...
- [CSP-S模拟测试]:小奇的仓库(warehouse)(树形DP)
题目背景 小奇采的矿实在太多了,它准备在喵星系建个矿石仓库.令它无语的是,喵星系的货运飞船引擎还停留在上元时代! 题目描述 喵星系有$n$个星球,星球以及星球间的航线形成一棵树.从星球$a$到星球$b ...
- [CSP-S模拟测试]:小奇的矩阵(matrix)(DP+数学)
题目背景 小奇总是在数学课上思考奇怪的问题. 题目描述 给定一个$n\times m$的矩阵,矩阵中的每个元素$a_{i,j}$为正整数.接下来规定: $1.$合法的路径初始从矩阵左上角出发,每 ...
- [CSP-S模拟测试]:小奇挖矿2(DP+赛瓦维斯特定理)
题目背景 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎. 题目描述 现在有$m+1$个星球,从左到右标号为$0$到$n$,小奇最初 ...
- [CSP-S模拟测试]:小Y的图(最小生成树+LCA)
题目传送门(内部题131) 输入格式 第一行三个整数$n$.$m$和$Q$. 接下来$m$行每行三个整数$x$.$y$.$z$($1\leqslant x,y\leqslant n,1\leqslan ...
- [CSP-S模拟测试]:小W的魔术(数学 or 找规律)
题目传送门(内部题130) 输入格式 第一行一个整数$n$,表示字符串的长度. 第二行一个只包含小写字母的字符串$s$. 输出格式 一行一个整数表示答案对$998244353$取模后的结果. 样例 样 ...
随机推荐
- Java实验3与第五周总结
1.已知字符串:"this is a test of java".按要求执行以下操作:(要求源代码.结果截图.) •统计该字符串中字母s出现的次数. •统计该字符串中子串" ...
- BusyBox TFTP使用(转)
开发板上使用TFTP 帮助信息: BusyBox v1.13.3 (2009-03-25 15:48:45 CST) multi-call binary Usage: tftp [OPTION]... ...
- 基于webstorm卡顿问题的2种解决方法
基于webstorm卡顿问题的2种解决方法:https://www.jb51.net/article/128441.htm
- adb 配置连接
一. adb环境安装 1.1. windown 驱动安装 1. 下载驱动(ADB Kits):http://adbshell.com/downloads 2. adb 测试 <1>. 解压 ...
- 区间gcd
http://codeforces.com/problemset/problem/914/D 题意:给你n个数,两种操作:1.询问区间[l,r]在至多一次修改一个数的条件下区间gcd是否等于x. 2. ...
- zebra代码分析
http://blog.csdn.net/xuyanbo2008/article/details/7439738
- PowerEdge T630服务器安装机器学习环境(Ubuntu18.04、Nvidia 1080Ti驱动、CUDA及CUDNN安装)
安装步骤 在开始安装之前,我要说明一下,这个Ubuntu18.04系统的安装,使用的连接线(就是服务器和电脑显示器的连接线)必须两头都是VGA连接线,不能使用VGA转HDMI连接线,也不能用DVI转D ...
- GUI学习之三十二—QLCDNumber学习总结
下面我们来总结一下QLCDNumber的用法 一.描述 QLCDNumber主要用来展示LCD样式的数字,他可以显示几乎任何大小的数字,可以显示十进制,十六进制,八进制或二进制数,也可以展示一些简单的 ...
- 九、ARM 汇编与 C 的混合编程
9.1 ARM 汇编与 C 的混合编程 9.1.1 内嵌汇编 __asm __asm("指令")例如关闭/打开总中断开关 CPSR __asm //使用 C 中变量名代替寄存器 { ...
- 爱奇艺免费vip观看地址
本人qq群也有许多的技术文档,希望可以为你提供一些帮助(非技术的勿加). QQ群: 281442983 (点击链接加入群:http://jq.qq.com/?_wv=1027&k=29Lo ...