计蒜客NOIP模拟赛4 D1T3 小X的佛光

小 X 是远近闻名的学佛,平日里最喜欢做的事就是蒸发学水。

小 X 所在的城市 X 城是一个含有 N 个节点的无向图,同时,由于 X 国是一个发展中国家,为了节约城市建设的经费,X 国首相在建造 X 城时只建造 N – 1 条边,使得城市的各个地点能够相互到达。

小 X 计划蒸发 Q 天的学水,每一天会有一名学水从 A 地走到 B 地,并在沿途各个地点留下一个水塘。此后,小 X 会从 C 地走到 B 地,并用佛光蒸发沿途的水塘。由于 X 城是一个学佛横行的城市,学水留下的水塘即使没有被小 X 蒸发,也会在第二天之前被其他学佛蒸发殆尽。

现在,小 X 想要知道,他每一天能够蒸发多少水塘呢?

输入格式

第一行三个整数 N,Q,num,分别表示 X 城地点的个数,小 X 蒸发学水的天数,以及测试点编号。注意,测试点编号是为了让选手们更方便的获得部分分,你可能不需要用到这则信息,在下发的样例中,测试点编号的含义是该样例满足某一测试点限制。

接下来 N – 1 行,每行两个整数 X,Y,表示 X 地与 Y 地之间有一条边。

接下来 Q 行,每行三个整数 A,B,C,表示一天中,有一名学水从 A 地走到 B 地,而小 X 会从 C 地走到 B 地。

输出格式

输出 Q 行,每行一个整数,表示小 X 能够蒸发的水塘数。

数据规模与约定

特殊性质 1:第 i 条边连接第 i 和第 i+1 个地点。

特殊性质 2A=C

样例输入

3 3 1
1 2
2 3
1 2 3
1 1 3
3 1 3

样例输出

1
1
3
A->B与B->C的共同路径长为
(LAB+LBC-LAC)/2
不过因为是点权,所以要+1
直接倍增LCA就行了
不过建树不能用dfs,会溢出,要用bfs()
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 using namespace std;
 7 struct Node
 8 {
 9     int next,to;
10 }edge[400001];
11 int num,head[200001];
12 int n,q,dep[200001],fa[200001][20];
13 bool vis[200001];
14 void add(int u,int v)
15 {
16     num++;
17     edge[num].next=head[u];
18     head[u]=num;
19     edge[num].to=v;
20 }
21 void bfs()
22 {int i;
23  queue<int>Q;
24  memset(vis,0,sizeof(vis));
25   dep[1]=1;
26  Q.push(1);
27  vis[1]=1;
28   while (Q.empty()==0)
29   {
30       int u=Q.front();
31       Q.pop();
32       for (i=head[u];i;i=edge[i].next)
33       {
34           int v=edge[i].to;
35           if (vis[v]==0)
36           {
37               vis[v]=1;
38               dep[v]=dep[u]+1;
39               fa[v][0]=u;
40               Q.push(v);
41           }
42       }
43   }
44 }
45 int LCA(int x,int y)
46 {int i;        
47     if (dep[x]<dep[y]) swap(x,y);
48     for (i=18;i>=0;i--)
49         if ((1<<i)<=dep[x]-dep[y]) x=fa[x][i];
50  if (x==y) return x; 
51  while (x!=y)
52  {
53     for (i=18;i>=0;i--)
54         if (fa[x][i]!=fa[y][i])
55         {
56             x=fa[x][i];
57             y=fa[y][i];
58         }
59 
60     if (x==y) return x;
61     x=fa[x][0];
62     y=fa[y][0];
63  }
64     return x;
65 }
66 int main()
67 {int x,y,i,a,b,c,j;
68     cin>>n>>q>>x;
69     for (i=1;i<=n-1;i++)
70     {
71         scanf("%d%d",&x,&y);
72         add(x,y);add(y,x);
73     }
74      bfs();
75  for (i=1;i<=n;i++)
76     {
77      for (j=1;j<=18;j++)
78          fa[i][j]=fa[fa[i][j-1]][j-1];
79     }
80     for (i=1;i<=q;i++)
81     {
82         scanf("%d%d%d",&a,&b,&c);
83         int l1=LCA(a,b),l2=LCA(b,c),l3=LCA(a,c);
84         int s1=dep[a]-dep[l1]+dep[b]-dep[l1];
85         int s2=dep[b]-dep[l2]+dep[c]-dep[l2];
86         int s3=dep[a]-dep[l3]+dep[c]-dep[l3];
87         printf("%d\n",(s1+s2-s3)/2+1);
88     } 
89 }

 

posted @ 2017-09-24 21:40  Z-Y-Y-S  阅读(548)  评论(2编辑  收藏  举报