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 < ...
随机推荐
- Linux locate 文件搜索
在学习 兄弟连 linux教学视频 的时候,我将所学的 linux 命令记录在我的博客中,方便自己查阅. 文件处理命令:locate 基础的命令 命令名称:locate 命令的所在路径:/usr/bi ...
- 网络编程-http连接-GET&POST
GetRequest package com.net.http; import java.io.BufferedReader; import java.io.IOException; import j ...
- Swift3.0 Set
set的简单的使用方法 //创建一个空set var letters = Set<Character>() //数组字面量创建set,只能存放string var setColors:Se ...
- Codeforces764C【DFS】
前言,根据最终图的样貌搞真厉害 "缩点判根度为结点数-1"牛逼 ----- 题意: 找一个根使得不带根的所有子树内部颜色都相同: 思路: 如果存在两个颜色不一样的连在一起,根就是他 ...
- 51nod 1011 【完全背包】
完全背包的变形: 这些数字可以取多次,dp[i]代表前 i 物品组成N时的方案数. #include<iostream> #include<cstring> #include& ...
- gns3 拖出设备显示一个红色的s,无法启动虚拟设备
通过view-docks-调出console窗口,显示错误信息: Error while creating project: Can't connect to server http://172.0. ...
- [题解]数学期望_luogu_P1850_换教室
数学期望dp,题面第一次见很吓人,然而从CCF语翻译成人话就简单多了, 开始一般会想到用 f [ i ] [ j ]表示前 i 个课程申请 j 次的期望,然而其实会发现转移的时候还和上一次的情况有关( ...
- bzoj1492 [NOI2007]货币兑换Cash【cdq分治】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1492 推荐博客:http://www.cnblogs.com/zig-zag/archive ...
- 洛谷 P3462 [POI2007]ODW-Weights
题面: https://www.luogu.org/problemnew/show/P3462 https://www.lydsy.com/JudgeOnline/problem.php?id=111 ...
- 使用高性能Pipelines构建.NET通讯程序
.NET Standard支持一组新的API,System.Span, System.Memory,还有System.IO.Pipelines.这几个新的API极大了提升了.NET程序的效能,将来.N ...