zoukankan      html  css  js  c++  java
  • 模拟赛T2 中继系统


    分析:
    实际上就分析一发最小生成树的变化
    但是时间是到正无穷,如果对于每个时刻都维护一下,显然是不可做的
    我们尝试分析一下最小生成树在什么时候改变
    当非最小生成树的边比最小生成树的边小的时候,最小生成树就会改变
    尝试枚举一对边复杂度为(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
    ",ans);
    }
    

  • 相关阅读:
    Linux:看门狗watchdog.sh程序编写示例
    通用linux程序看门狗(watchdog)python版
    Linux看门狗脚本 1.4
    Qt 6中的输入事件
    使用Qt5Compat库从Qt 5移植到Qt 6
    vertical-align(mozilla的在线帮助)
    css文字如何垂直居中?
    JS-apply 、call 以及 bind
    敢放手把事情给别人做
    页面----调用本地程序
  • 原文地址:https://www.cnblogs.com/Darknesses/p/12316202.html
Copyright © 2011-2022 走看看