UVA - 1279 Asteroid Rangers (动点的最小生成树)
题意,有n个匀速动点,求最小生成树的改变次数。
一句话总结:动态问题的一般做法是先求出一个静态的解,然后求出解发生改变的事件,事件按照时间排序,依次处理。
先求出最开始的最小生成树(MST),当MST中的某条线段v长度被不在MST的线段u取代的时候,最小生成树才会发生变化,
具体来说,已经知道之前的MST,边按照长度排序,在这个时间点之前的瞬间,v一定是MST最长的边,u紧跟在v之后,在这个时间点之后u和v的位置交换了一下,
根据Kruskal算法,对于u和v之前的边没有影响,前面的边连完以后如果u的两个端点不在同一个连通分量里,那么u会被加入形成新的MST,否则MST不变。
根据边长的平方对时间的函数求出所有线段u和v长度相等且之后u更短的时间点,按照时间顺序排序,一旦满足上述条件,就修改MST。
为了维护MST需要维护一个MST到边的映射,为了判断新线段在不在MST中以及忽略旧边需要维护一个边到MST编号的映射。
求时间点时有解的三种情况:
一开始先对线段长度排过序,所以保证Lj>Li,
第一种情况是a=0,一个解,之后j更短。
第二种情况是a<0,因为Lj>Li,所以只有大的那个是合法的,之后j更短。
第三种情况,a>0,第一个解是j更短,第二个解是i更短。
#include<bits/stdc++.h>
using namespace std; const double eps = 1e-; struct Event
{
double t;
int u,v; //这个时间点以后u更短
bool operator < (const Event& r) const {
return t < r.t;
}
}; vector<Event> events;
#define PB push_back
const int maxn = ;
const int maxl = maxn*(maxn-)>>; struct Point
{
double x,y,z,dx,dy,dz;
void read(){ scanf("%lf%lf%lf%lf%lf%lf",&x,&y,&z,&dx,&dy,&dz); }
Point operator - (const Point&r) { return {x-r.x, y-r.y, z-r.z, dx-r.dx, dy-r.dy, dz-r.dz}; }
}P[maxn]; #define squ(x) ((x)*(x)) struct Seg
{
double a,b,c;
int u,v;
void cal(int i,int j){
u = i; v = j;
Point t = P[i]-P[j];
a = squ(t.dx) + squ(t.dy) + squ(t.dz);
b = *(t.dx*t.x + t.dy*t.y + t.dz*t.z);
c = squ(t.x) + squ(t.y) + squ(t.z);
}
}L[maxl]; bool operator < (const Seg&x, const Seg&y) { return x.c < y.c; } int lcnt;
int n; //if equation has two roots, r1 < r2
int solveEqu(double a,double b,double c,double &r1,double &r2)
{
if(fabs(a)<eps){
if(fabs(b)<eps) return ;
r1 = -c/b;
return ;
}
double delta = b*b-.*a*c;
if(delta<eps) return ;
delta = sqrt(delta);
if(a>){
r1 = (-b-delta)/(.*a);
r2 = (-b+delta)/(.*a);
}else {
r1 = (-b+delta)/(.*a);
r2 = (-b-delta)/(.*a);
}
return ;
} int pa[maxl]; int pos[maxl]; //map: Edge to MST
int e[maxn]; //map: MST to Edge void initUFS() { for(int i = ; i < n; i++) pa[i] = i; }
int Find(int x) { return x == pa[x]?x:pa[x]=Find(pa[x]); } int main()
{
//freopen("in.txt","r",stdin);
int kas = ;
while(~scanf("%d",&n)){
for(int i = ; i < n; i++) P[i].read();
events.clear(); lcnt = ;
for(int i = ; i < n; i++){
for(int j = i+; j < n; j++){
L[lcnt++].cal(i,j);
}
}
sort(L,L+lcnt);//ascending order for(int i = ; i < lcnt; i++){
for(int j = i+; j < lcnt; j++){
double r[];
double a = L[j].a - L[i].a//j相对i的长度
, b = L[j].b - L[i].b
, c = L[j].c - L[i].c; int rcnt = solveEqu(a,b,c,r[],r[]);
if(rcnt == ){
if(r[]>) events.PB({r[],j,i});
}else if(rcnt == ){
if(a<){
if(r[]>) events.PB({r[],j,i});
}else {
if(r[]>) events.PB({r[],j,i});
if(r[]>) events.PB({r[],i,j});
} }
}
}
sort(events.begin(),events.end());
//DeBugEv
initUFS();
memset(pos,,sizeof(int)*lcnt); int idx = ;
for(int i = ; i < lcnt; i++){
int s1 = Find(L[i].u), s2 = Find(L[i].v);
if(s1 != s2){
pa[s1] = s2;
e[pos[i] = ++idx] = i; //e[] 下标从1开始。0表不在MST中
if(idx == n-) break;
}
} int ans = ;
for(int i = ; i < events.size(); i++){
Event &ev = events[i];
if(pos[ev.v]&&!pos[ev.u]){
initUFS();
int old = pos[ev.v];
for(int j = ; j <= idx; j++){
if(j == old) continue;
int s1 = Find(L[e[j]].u), s2 = Find(L[e[j]].v);
if(s1 != s2){ pa[s1] = s2; }
}
int s1 = Find(L[ev.u].u), s2 = Find(L[ev.u].v);
if(s1 != s2){
ans++;
pos[ev.u] = old;
pos[ev.v] = ;
e[old] = ev.u;
}
}
}
printf("Case %d: %d\n",++kas,ans);
}
return ;
}
UVA - 1279 Asteroid Rangers (动点的最小生成树)的更多相关文章
- 紫书 例题 11-14 UVa 1279 (动点最小生成树)(详细解释)
这道题写了好久-- 在三维空间里面有动的点, 然后求有几次最小生成树. 其实很容易发现, 在最小生成树切换的时候,在这个时候一定有两条边相等, 而且等一下更大的那条边在最小生成树中,等一下更小的边不在 ...
- UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)
题意: 要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方大小的花费,这说明每两个点都可以使其互通.接着有q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需 ...
- UVA:11183:Teen Girl Squad (有向图的最小生成树)
Teen Girl Squad Description: You are part of a group of n teenage girls armed with cellphones. You h ...
- 【uva 1395】Slim Span(图论--最小生成树+结构体快速赋值 模版题)
题意:给一个N(N<=100)个点的联通图(无自环和平行边),求苗条度(最大边-最小边的值)尽量小的生成树. 解法:枚举+Kruskal.先从小到大排序边,枚举选择的最小的边. 1 #inclu ...
- UVALive 4080 Warfare And Logistics (最短路树)
很多的边会被删掉,需要排除一些干扰进行优化. 和UVA - 1279 Asteroid Rangers类似,本题最关键的地方在于,对于一个单源的最短路径来说,如果最短路树上的边没有改变的话,那么最短路 ...
- 训练指南 UVA- 11865(有向最小生成树 + 朱刘算法 + 二分)
layout: post title: 训练指南 UVA- 11865(有向最小生成树 + 朱刘算法 + 二分) author: "luowentaoaa" catalog: tr ...
- 关于最小生成树 Kruskal 和 Prim 的简述(图论)
模版题为[poj 1287]Networking. 题意我就不说了,我就想简单讲一下Kruskal和Prim算法.卡Kruskal的题似乎几乎为0.(●-`o´-)ノ 假设有一个N个点的连通图,有M条 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 基尔霍夫矩阵题目泛做(AD第二轮)
题目1: SPOJ 2832 题目大意: 求一个矩阵行列式模一个数P后的值.p不一定是质数. 算法讨论: 因为有除法而且p不一定是质数,不一定有逆元,所以我们用辗转相除法. #include < ...
随机推荐
- 【Data Structure & Algorithm】二叉树中和为某值的所有路径
二叉树中和为某值的所有路径 题目:输入一个整数和一个二叉树,从树的根节点开始往下访问一直到叶节点所经过的所有节点形成一条路径.打印出和与输入整数相等的所有路径. 例如输入整数22和如下二叉树: 10 ...
- POJ - 3494 Largest Submatrix of All 1’s 单调栈求最大子矩阵
Largest Submatrix of All 1’s Given a m-by-n (0,1)-matrix, of all its submatrices of all 1’s which is ...
- 【阿里云IoT+YF3300】1.时代大背景下的阿里云IoT物联网的现状和未来
“未来十到二十年,大家基本已经形成了一个共识,那便是新格局的奠定将由 AI 和物联网技术来支撑.放眼国内,在这些互联网巨头之中,未来真正成为竞争对手厮杀的,阿里和华为是首当其冲,在这两个领域双方分别暗 ...
- MySql 5.6 遇到的一些问题
1. 卸载5.5之后,使用 mysql installer 时,没法设定 data directory . 最后再次删除mysql installer之后,使系统干净后才能重新安装, 然后界面出现了 ...
- LCT 动态树 模板
洛谷:P3690 [模板]Link Cut Tree (动态树) /*诸多细节,不注意就会调死去! 见注释.*/ #include<cstdio> #include<iostream ...
- [Xcode 实际操作]八、网络与多线程-(15)使用网址会话对象URLSession下载图片并存储在沙箱目录中
目录:[Swift]Xcode实际操作 本文将演示如何通过网址会话对象URLSession下载图片并存储在沙箱目录中. 网址会话对象URLSession具有在后台上传和下载.暂停和恢复网络操作.丰富的 ...
- 给 UILabel 中的文字增加 line-through / Strikethrough (删除线)样式
iOS 6 中苹果引入了 NSStrikethroughStyleAttributeName 属性,用于设置 NSAttributedString 的删除线样式,用法如下: let attribute ...
- Mysql相关函数使用和总结(cast、convert)
一.类型转换 1.获取一个类型的值,并产生另一个类型的值,CAST()和CONVERT()函数. 用法: CAST(value as type); CONVERT(value, type); 解释:C ...
- 统一入口&DB代理思想
参考 https://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650764278&idx=2&sn=b7801fb0780 ...
- ZJOI2017 day2 T2 线段树 想法题
考完D2发现自己简直zz了...花式扔基本分 首先这道题有个显然的套路:树上一些点到一个定点的距离和=这些点深度和+点数*定点深度和-2*lca深度和 ——上一次见这个套路是LNOI2014,上次做的 ...