您的位置:首页 > 其它

CF519E A and B and Lecture Rooms

2018-09-29 10:43 309 查看

题目传送门

这道题目...真是一道好题...题出的好!难度适中!覆盖知识点广!题目有着切合实际的背景!解法比较自然!给出题人点赞 !

题意:

  给你一棵树,每次询问给出两个点,问树上有多少点到这两个点的距离相等。

$Sol$


树上距离...嗯肯定有$LCA$,但是看起来还是毫无思路的样子啊...怎么办。

这个时候分类讨论一定是个不错的选择(逃)

 

由于我只会树上倍增,而且大部分时候它还是很好用的,还能求出许多附属需要的东西,所以我们先用树上倍增法求出树上这两点的距离,进行分类讨论。(设置一个a的深度大于b的深度的前提)

1)当距离为奇数:无解,答案为0.

1 #include<cstdio>
2 #include<algorithm>
3 #include<queue>
4 #include<cmath>
5 #define maxn 100090
6
7 using namespace std;
8
9 int n,m,tot,t;
10 int head[maxn],size[maxn],d[maxn];
11 int f[maxn][30];
12 bool vis[maxn];
13 struct node{
14     int to,next;
15 }edge[maxn*2];
16
17 void add(int x,int y)
18 {
19     edge[++tot].to=y;
20     edge[tot].next=head[x];
21     head[x]=tot;
22 }
23
24 void init_1()
25 {
26     queue<int>q;
27     q.push(1);d[1]=1;
28     while(!q.empty())
29     {
30         int u=q.front();q.pop();
31         for(int i=head[u];i;i=edge[i].next)
32         {
33             int v=edge[i].to;
34             if(d[v]) continue;
35             d[v]=d[u]+1;
36             f[v][0]=u;
37             for(int j=1;j<=t;j++)
38                 f[v][j]=f[f[v][j-1]][j-1];
39             q.push(v);
40         }
41     }
42 }
43
44 void init_2(int u)
45 {
46     vis[u]=1;size[u]++;
47     for(int i=head[u];i;i=edge[i].next)
48     {
49         int v=edge[i].to;
50         if(vis[v]) continue;
51         init_2(v);
52         size[u]+=size[v];
53     }
54 }
55
56 int find(int x,int dep)
57 {
58     int hu=x;
59     for(int i=t;i>=0;i--)
60     {
61         if(d[hu]-(1<<i)<dep) continue;
62         hu=f[hu][i];
63     }
64     return hu;
65 }
66
67 int ask(int x,int y)
68 {
69     if(d[x]<d[y]) swap(x,y);
70     int prex=x,prey=y,lca=0,tmp=0;
71     for(int i=t;i>=0;i--)
72         if(d[f[x][i]]>=d[y]) x=f[x][i];
73     if(x==y) lca=x;
74     else
75     {
76         for(int i=t;i>=0;i--)
77             if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
78         lca=f[x][0];
79     }
80     x=prex,tmp=y,y=prey;
81     int dis=d[x]+d[y]-2*d[lca];
82     if(dis&1) return 0;
83     if(lca==y)
84     {
85         int mid=(d[x]+d[y])>>1;
86         return size[find(x,mid)]-size[find(x,mid+1)];
87     }
88     else
89     {
90         if(d[x]==d[y])
91             return n-size[find(x,d[lca]+1)]-size[find(y,d[lca]+1)];
92         else
93         {
94             int mid=d[x]-(dis>>1);
95             return size[find(x,mid)]-size[find(x,mid+1)];
96         }
97     }
98 }
99
100 int main()
101 {
102     scanf("%d",&n);
103     t=log2(n)+1;
104     for(int i=1;i<=n-1;i++)
105     {
106         int x=0,y=0;
107         scanf("%d%d",&x,&y);
108         add(x,y);add(y,x);
109     }
110     init_1();
111     init_2(1);
112     scanf("%d",&m);
113     for(int i=1;i<=m;i++)
114     {
115         int x=0,y=0;
116         scanf("%d%d",&x,&y);
117         if(x==y){printf("%d\n",n);continue;}
118         printf("%d\n",ask(x,y));
119     }
120     return 0;
121 }
View Code  

参考文献:https://www.cnblogs.com/qixingzhi/p/9302038.html(从这里学会的)

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: