标签:getc clu main 变化 关系 左右 check return def
分析:
实际上就分析一发最小生成树的变化
但是时间是到正无穷,如果对于每个时刻都维护一下,显然是不可做的
我们尝试分析一下最小生成树在什么时候改变
当非最小生成树的边比最小生成树的边小的时候,最小生成树就会改变
尝试枚举一对边复杂度为\(O(n^4)\)
这对边在什么时候大小关系产生改变,实际上是一个一元二次方程
直接暴力解就好了
然后对于每一个时间点,如果维护的生成树中,一对边一个在树内,一个在树外,就要对生成树进行改变
但是不能全部维护复杂度为\(O(n^6)\),我们只需要把相关的链上的边单独维护,这样复杂度就变成了\(O(n^5)\)
常数上为除以10左右,写得漂亮一点就过了2333
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<queue>
#define maxn 55
#define INF 0x3f3f3f3f
#define MOD 998244353
#define eps 1e-7
using namespace std;
inline long long getint()
{
long long num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
struct edge{
int u,v;
double w;
}L[maxn*maxn],stk[2][maxn],now[maxn*maxn];
struct node{
int u,v;
double t;
}T[maxn*maxn*maxn*maxn];
int n,ans;
double p[maxn][20];
int cnte,cntl,cntnow,tp[2];
int fa[maxn];
bool vis[maxn][maxn];
inline double geta(int i,int j)
{double num=0;for(int k=1;k<=3;k++)num+=(p[i][k+3]-p[j][k+3])*(p[i][k+3]-p[j][k+3]);return num;}
inline double getb(int i,int j)
{double num=0;for(int k=1;k<=3;k++)num+=2*(p[i][k]-p[j][k])*(p[i][k+3]-p[j][k+3]);return num;}
inline double getc(int i,int j)
{double num=0;for(int k=1;k<=3;k++)num+=(p[i][k]-p[j][k])*(p[i][k]-p[j][k]);return num;}
inline void insert(int i,int j,double t)
{if(t<=0)return;T[++cnte].u=i,T[cnte].v=j,T[cnte].t=t;}
bool cmp1(node a,node b){return a.t<b.t;}
bool cmp2(edge a,edge b){return a.w<b.w;}
bool cmp3(edge a,edge b){return a.u==b.u?a.v<b.v:a.u<b.u;}
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void Krus()
{
memset(vis,0,sizeof vis);
sort(L+1,L+cntl+1,cmp2);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=cntl;i++)
{
int r1=find(L[i].u),r2=find(L[i].v);
if(r1!=r2)
{
fa[r2]=r1;
now[++cntnow]=L[i];
vis[L[i].u][L[i].v]=vis[L[i].v][L[i].u]=true;
}
}
}
inline bool check(edge x){return vis[x.u][x.v]?1:0;}
inline void solve(int id,double t)
{
for(int i=1,u,v;i<=cntnow;i++)
{
u=now[i].u,v=now[i].v;now[i].w=0;
for(int k=1;k<=3;k++)now[i].w+=(p[u][k]+t*p[u][k+3]-p[v][k]-t*p[v][k+3])*(p[u][k]+t*p[u][k+3]-p[v][k]-t*p[v][k+3]);
}
for(int i=1;i<=n;i++)fa[i]=i;
sort(now+1,now+cntnow+1,cmp2);
tp[id]=0;
for(int i=1;i<=cntnow;i++)
{
int r1=find(now[i].u),r2=find(now[i].v);
if(r1!=r2)
{
fa[r2]=r1;++tp[id];
stk[id][tp[id]].u=now[i].u,stk[id][tp[id]].v=now[i].v;
}
}
}
int main()
{
n=getint();
for(int i=1;i<=n;i++)for(int k=1;k<=6;k++)p[i][k]=getint();
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
L[++cntl].u=i,L[cntl].v=j;
for(int k=1;k<=3;k++)L[cntl].w+=(p[i][k]-p[j][k])*(p[i][k]-p[j][k]);
}
for(int i=1;i<=cntl;i++)
for(int j=i+1;j<=cntl;j++)
{
double a=geta(L[i].u,L[i].v)-geta(L[j].u,L[j].v),b=getb(L[i].u,L[i].v)-getb(L[j].u,L[j].v),c=getc(L[i].u,L[i].v)-getc(L[j].u,L[j].v);
if(fabs(a)<eps)
{
if(fabs(b)<eps)continue;
insert(i,j,-c/b);
}
else
{
double delta=b*b-4*a*c;if(delta<0)continue;
insert(i,j,(-b+sqrt(delta))/(2*a)),insert(i,j,(-b-sqrt(delta))/(2*a));
}
}
sort(T+1,T+cnte+1,cmp1);
ans=1;Krus();
sort(L+1,L+cntl+1,cmp3);
for(int i=1,flag=0,p1,p2;i<=cnte;i++)
{
p1=check(L[T[i].u]),p2=check(L[T[i].v]);
if(p1^p2)
{
if(!p1)now[++cntnow]=L[T[i].u];
else now[++cntnow]=L[T[i].v];
flag=1;
}
if(fabs(T[i].t-T[i+1].t)>eps&&flag)
{
solve(0,T[i].t-eps);
solve(1,T[i].t+eps);
sort(stk[0]+1,stk[0]+tp[0]+1,cmp3);
sort(stk[1]+1,stk[1]+tp[1]+1,cmp3);
int g=0;
cntnow=0;
memset(vis,0,sizeof vis);
for(int i=1;i<n;i++)
{
if(!(stk[0][i].u==stk[1][i].u&&stk[0][i].v==stk[1][i].v))g=1;
now[++cntnow]=stk[1][i];
vis[stk[1][i].u][stk[1][i].v]=vis[stk[1][i].v][stk[1][i].u]=true;
}
ans+=g;
}
if(fabs(T[i].t-T[i+1].t)>eps)flag=0;
}
printf("%d\n",ans);
}
标签:getc clu main 变化 关系 左右 check return def
原文地址:https://www.cnblogs.com/Darknesses/p/12316202.html