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 < ...
随机推荐
- SQL Server之null
数据库中,一个列如果没有指定值,那么值就为null,数据库中的null表示unknown“不知道”,而不是表示没有.因此select null+1结果是null,因为“不知道”加1的结果还是“不知道” ...
- JAVA企业级开发-session,cookie(13)
一. jsp jsp: java server pager .java动态生成网页的一门技术 使用servlet生成网页时候遇到的问题,为什么使用jsp? 在servlet里面书写htm ...
- Swift协议中类继承协议的mutating问题
之前实际开发的时候遇到的一个小问题,网上也没有找到相关说明.本来当时弄明白了想着记下来的,但是比较忙就耽搁了,趁今天休息记录一下. 首先,我们看一下下面这个两数之和的协议 protocol Test: ...
- bzoj3453: tyvj 1858 XLkxc(拉格朗日插值)
传送门 \(f(n)=\sum_{i=1}^ni^k\),这是自然数幂次和,是一个以\(n\)为自变量的\(k+1\)次多项式 \(g(n)=\sum_{i=1}^nf(i)\),因为这东西差分之后是 ...
- Luogu P1092 虫食算【搜索/剪枝】 By cellur925
题目传送门 这道题是一道经久不衰的搜索题目,但是开始做的时候我没什么思路==.初始值-1 输出格式 \(naive\)想法 从右往左依次尝试填充数字,把算式当做一个3行\(n\)列的网格.(什么?你问 ...
- RN初始化项目报错
解决方法:全局删除yarn
- android okhttp和webview session共享
public static OkHttpClient get(Context context){ OkHttpClient.Builder builder = new OkHttpClient.Bui ...
- [題解](最短路/二分)luogu_P1462通往奧格瑞瑪的道路
看到最大的最小值應該想到二分答案,這樣就解決了最小點權的問題,判血量就很好說,直接比較就行, 一個點是二分點權數組,複製一份然後排序,二分下標,速度較快 這麼簡單的題我竟然寫了這麼長時間 #inclu ...
- SSIS Passing Parameters to an ADO .NET Source query;向ado.net数据源传递参数。
使用SSIS的oledb数据源时的参数按钮如下图: 但是在使用ADO.NET源连接到MYSQL时,没有这个参数按钮,如何向数据流的sql command传递参数呢? steps: 1. 在 控制流 选 ...
- json数据有换行符时提交不成功的坑
这是在有多行文本框表单提交时遇到的问题.. 整理所有的表达数据,合并到一个json中然后jsonp方式提交给后端时,发现只要有换行符,总是提交失败. 目前的解决办法就是在合并数据的时候把换行\n替换为 ...