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\n",(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\n",(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\n",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 }

 

转载于:https://www.cnblogs.com/zhuohan123/p/3698852.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值