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 < ...
随机推荐
- SqlServer2012——表
1.数据类型 数字类型:int,smallint, 高精度:decimal,numeric 日期和时间:datetime,smalldatetime 二进制:binary,varbinary,imag ...
- CodeForces——Game with string(STL stack栈)
Two people are playing a game with a string ss, consisting of lowercase latin letters. On a player's ...
- 强大的在线web编辑器UEditor
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. UEditor在线演示地址:http://u ...
- 笔记-JavaWeb学习之旅13
验证码案列 昨天晚上出现的500错误原因在于验证码没有获取到,获取验证码是应该获取的是共享域中的验证码,而我把获取值得键给写成了jsp中的键,而不是内存生成图片中,然后把图片上传到共享域中的键.这两个 ...
- 普通组件定义渲染和render渲染组件的区别(三)
普通方式定义组件和效果: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- 最简大数据Spark-2.1.0
0.0 前言 本文主要基于最新的Spark 2.1.0版本.阅读本文可以对Spark 2.1.0的学习过程,运行流程,关键组件,原理有所了解.文章有点长,你也可以直接阅读感兴趣的部分,但是还是建议全面 ...
- D. Pair Of Lines( Educational Codeforces Round 41 (Rated for Div. 2))
#include <vector> #include <iostream> #include <algorithm> using namespace std; ty ...
- php—Spl库常用数据结构基本用法
数据结构之一 : 栈 //zhan $stack = new SplStack(); $stack->push('data1'); $stack->push('data2'); echo ...
- 530 Minimum Absolute Difference in BST 二叉搜索树的最小绝对差
给定一个所有节点为非负值的二叉搜索树,求树中任意两节点的差的绝对值的最小值.示例 :输入: 1 \ 3 / 2输出:1解释:最小绝对差为1,其中 2 和 1 的差的绝对值为 ...
- C51 笔记
一 关于宏常量的长度:C51中定义一个常数宏(默认是16位的),如果用宏表示一个32位的宏而不加'L'标志的话就会出错.如 #define BLOCK_A_BASEADDR 18*64*1024 / ...