zoukankan      html  css  js  c++  java
  • BZOJ3528: [Zjoi2014]星系调查

    唉,看到这题直接想起自己的Day1,还是挺难受的,挺傻一题考试的时候怎么就没弄出来呢……

    这两天CP让我给他写个题解,弄了不是很久就把这个题给弄出来了,真不知道考试的时候在干嘛。

    明天就出发去北京了,祝自己APIO顺利吧。

      1 /**************************************************************
      2     Problem: 3528
      3     User: zhuohan123
      4     Language: C++
      5     Result: Accepted
      6     Time:1736 ms
      7     Memory:25408 kb
      8 ****************************************************************/
      9  
     10 #include <iostream>
     11 #include <cmath>
     12 #include <cstdio>
     13 #include <cstring>
     14 #include <algorithm>
     15 using namespace std;
     16 const double eps=1e-7;
     17 inline int getnum()
     18 {
     19     int ans=0,fh=1;char ch=getchar();
     20     while(ch<'0'||ch>'9'){if(ch=='-')fh*=-1;ch=getchar();}
     21     while(ch>='0'&&ch<='9')ans=ans*10+ch-'0',ch=getchar();
     22     return fh*ans;
     23 }
     24 struct info
     25 {
     26     int n,x,y,x2,y2,xy;
     27     info(){n=x=y=x2=y2=xy=0;}
     28     info(int X,int Y){n=1;x=X;y=Y;x2=X*X;y2=Y*Y;xy=X*Y;}
     29     info(int N,int X,int Y,int X2,int Y2,int XY){n=N;x=X;y=Y;x2=X2;y2=Y2;xy=XY;}
     30     inline friend info operator+(info a,info b){return info(a.n+b.n,a.x+b.x,a.y+b.y,a.x2+b.x2,a.y2+b.y2,a.xy+b.xy);}
     31     inline friend info operator-(info a,info b){return info(a.n-b.n,a.x-b.x,a.y-b.y,a.x2-b.x2,a.y2-b.y2,a.xy-b.xy);}
     32     inline info operator+=(info b){n+=b.n;x+=b.x;y+=b.y;x2+=b.x2;y2+=b.y2;xy+=b.xy;return *this;}
     33     inline double xbar(){return (double)x/(double)n;}
     34     inline double ybar(){return (double)y/(double)n;}
     35     inline double A(){return x2-2*xbar()*x+n*xbar()*xbar();}
     36     inline double B(){return 2*ybar()*x+2*xbar()*y-2*xy-2*n*xbar()*ybar();}
     37     inline double C(){return y2-2*ybar()*y+n*ybar()*ybar();}
     38     inline double delta()
     39     {
     40         if(n==1)return 0;
     41         double a=A(),b=B(),c=C(),d=sqrt(a*a+b*b+c*c-2*a*c);
     42         double ans1=(a+c+d)/2,ans2=(a+c-d)/2;
     43         if(ans1>ans2)swap(ans1,ans2);
     44         return ans1>-eps?ans1:ans2;
     45     }
     46 };
     47 int n,m;
     48 struct point
     49 {
     50     int head,f[20],deep,incir,wt;
     51     info x;
     52 }p[110000];
     53 struct edge{int next,to;}g[210000];int gnum;
     54 void addedge(int from,int to)
     55 {
     56     g[++gnum].to=to;g[gnum].next=p[from].head;p[from].head=gnum;
     57     g[++gnum].to=from;g[gnum].next=p[to].head;p[to].head=gnum;
     58 }
     59 namespace Tree
     60 {
     61     void dfs(int po)
     62     {
     63         p[po].deep=p[p[po].f[0]].deep+1;
     64         for(int i=1;i<=17;i++)
     65             p[po].f[i]=p[p[po].f[i-1]].f[i-1];
     66         for(int i=p[po].head;i;i=g[i].next)
     67             if(g[i].to!=p[po].f[0])
     68             {
     69                 p[g[i].to].x+=p[po].x;
     70                 p[g[i].to].f[0]=po;
     71                 dfs(g[i].to);
     72             }
     73     }
     74     inline int lca(int u,int v)
     75     {
     76         if(p[u].deep>p[v].deep)swap(u,v);
     77         for(int i=17;i>=0;i--)
     78             if(p[p[v].f[i]].deep>=p[u].deep)v=p[v].f[i];
     79         if(u==v)return u;
     80         for(int i=17;i>=0;i--)
     81             if(p[v].f[i]!=p[u].f[i])v=p[v].f[i],u=p[u].f[i];
     82         return p[v].f[0];
     83     }
     84     void solve()
     85     {
     86         dfs(1);
     87         int q=getnum();
     88         while(q--)
     89         {
     90             int u=getnum(),v=getnum(),l=lca(u,v);
     91             printf("%.5lf
    ",(p[u].x+p[v].x-p[l].x-p[p[l].f[0]].x).delta()+eps);
     92         }
     93     }
     94 }
     95 namespace Circle
     96 {
     97     bool ins[110000];
     98     int s[110000],sr;
     99     int cir[210000],cnum;
    100     info cinfo[210000];
    101     inline info cirwalk(int l,int r){return cinfo[r]-cinfo[l-1];}
    102     bool dfscir(int po,int from)
    103     {
    104         ins[s[++sr]=po]=true;
    105         for(int i=p[po].head;i;i=g[i].next)
    106             if(g[i].to!=from)
    107             {
    108                 if(ins[g[i].to])
    109                 {
    110                     while(s[sr]!=g[i].to)
    111                     {
    112                         cir[++cnum]=s[sr];
    113                         p[s[sr]].incir=cnum;
    114                         sr--;
    115                     }
    116                     cir[++cnum]=g[i].to;
    117                     p[g[i].to].incir=cnum;
    118                     return true;
    119                 }
    120                 else if(dfscir(g[i].to,po))return true;
    121             }
    122         sr--;
    123         ins[po]=false;return false;
    124     }
    125     void dfstree(int po,int wt)
    126     {
    127         p[po].wt=wt;
    128         p[po].deep=p[p[po].f[0]].deep+1;
    129         for(int i=1;i<=17;i++)
    130             p[po].f[i]=p[p[po].f[i-1]].f[i-1];
    131         for(int i=p[po].head;i;i=g[i].next)
    132             if(g[i].to!=p[po].f[0]&&!p[g[i].to].incir)
    133             {
    134                 p[g[i].to].x+=p[po].x;
    135                 p[g[i].to].f[0]=po;
    136                 dfstree(g[i].to,wt);
    137             }
    138     }
    139     inline int lca(int u,int v)
    140     {
    141         if(p[u].deep>p[v].deep)swap(u,v);
    142         for(int i=17;i>=0;i--)
    143             if(p[p[v].f[i]].deep>=p[u].deep)v=p[v].f[i];
    144         if(u==v)return u;
    145         for(int i=17;i>=0;i--)
    146             if(p[v].f[i]!=p[u].f[i])v=p[v].f[i],u=p[u].f[i];
    147         return p[v].f[0];
    148     }
    149     void solve()
    150     {
    151         dfscir(1,0);
    152         for(int i=1;i<=cnum;i++)dfstree(cir[i],cir[i]);
    153         for(int i=1;i<=cnum;i++)cir[i+cnum]=cir[i];
    154         for(int i=1;i<=2*cnum;i++)cinfo[i]=cinfo[i-1]+p[cir[i]].x;
    155         int q=getnum();
    156         while(q--)
    157         {
    158             int u=getnum(),v=getnum();
    159             if(p[u].wt==p[v].wt)
    160             {
    161                 int l=lca(u,v);
    162                 printf("%.5lf
    ",(p[u].x+p[v].x-p[l].x-p[p[l].f[0]].x).delta()+eps);
    163             }
    164             else
    165             {
    166                 int fu=p[u].wt,fv=p[v].wt;
    167                 info iu=p[u].x-p[fu].x,iv=p[v].x-p[fv].x;
    168                 if(p[fu].incir>p[fv].incir)swap(fu,fv);
    169                 info imid1=cirwalk(p[fu].incir,p[fv].incir);
    170                 info imid2=cirwalk(p[fv].incir,p[fu].incir+cnum);
    171                 printf("%.5lf
    ",min((iu+imid1+iv).delta(),(iu+imid2+iv).delta())+eps);
    172             }
    173         }
    174     }
    175 }
    176 int main(int argc, char *argv[])
    177 {
    178     //freopen("1.in","r",stdin);
    179     //freopen("1.out","w",stdout);
    180     n=getnum(),m=getnum();
    181     for(int i=1;i<=n;i++)
    182     {
    183         int x=getnum(),y=getnum();
    184         p[i].x=info(x,y);
    185     }
    186     for(int i=1;i<=m;i++)addedge(getnum(),getnum());
    187     if(m==n-1)Tree::solve();
    188     else Circle::solve();
    189     return 0;
    190 }
  • 相关阅读:
    第16周作业
    第15周作业
    迟到的第14周作业
    第13次作业集
    软件工程结课总结
    第13次作业
    第12次作业
    第11次作业--字符串的处理
    第10次作业(2)
    第十次作业
  • 原文地址:https://www.cnblogs.com/zhuohan123/p/3698852.html
Copyright © 2011-2022 走看看