luogu P3398 仓鼠找sugar [LCA]

题目描述

小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n。地下洞穴是一个树形结构。这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c)到图书馆(d)。他们都会走最短路径。现在小仓鼠希望知道,有没有可能在某个地方,可以碰到他的基友?

小仓鼠那么弱,还要天天被zzq大爷虐,请你快来救救他吧!

输入输出格式

输入格式:

第一行两个正整数n和q,表示这棵树节点的个数和询问的个数。

接下来n-1行,每行两个正整数u和v,表示节点u到节点v之间有一条边。

接下来q行,每行四个正整数a、b、c和d,表示节点编号,也就是一次询问,其意义如上。

输出格式:

对于每个询问,如果有公共点,输出大写字母“Y”;否则输出“N”。

输入输出样例

输入样例#1:
5 5
2 5
4 2
1 3
1 4
5 1 5 1
2 2 1 4
4 1 3 4
3 1 1 5
3 5 1 4
输出样例#1:
Y
N
Y
Y
Y

说明

本题时限1s,内存限制128M,因新评测机速度较为接近NOIP评测机速度,请注意常数问题带来的影响。

20%的数据 n<=200,q<=200

40%的数据 n<=2000,q<=2000

70%的数据 n<=50000,q<=50000

100%的数据 n<=100000,q<=100000


My Solution

借用题解里沧澜的原话:

如果两条路径相交,那么一定有一条路径的LCA在另一条路径上

而判断一个节点x,是否在路径s-t上需要满足如下几个条件

    - deep[x]>=deep[LCA(s,t)]

    - LCA(s,x)=x或LCA(t,x)=x;

所以分两种情况讨论一下即可

剩下的就是lca模板了,找根我用了点分治里找重心

暂时只会倍增lca  QwQ

再犯sb错误,把&打成了&&

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<vector>
  5 using namespace std;
  6 #define q1 first
  7 #define q2 second
  8 #define ss first
  9 #define tt second
 10 
 11 inline int read(){
 12     char ch;
 13     int re=0;
 14     bool flag=0;
 15     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
 16     ch=='-'?flag=1:re=ch-'0';
 17     while((ch=getchar())>='0'&&ch<='9')  re=re*10+ch-'0';
 18     return flag?-re:re;
 19 }
 20 
 21 struct edge{
 22     int to,next;
 23     edge(int to=0,int next=0):
 24         to(to),next(next){};
 25 };
 26 const int maxn=100001;
 27 const int maxm=maxn<<1;
 28 const int maxlogn=17;
 29 typedef pair<int,int> PII;
 30 typedef pair<PII,PII> PP;
 31 int n,q;
 32 vector<PP> ques;
 33 int cnt=0;
 34 int head[maxn];
 35 edge edges[maxm];
 36 int root;
 37 int F[maxn],son[maxn];
 38 bool vis[maxn];
 39 int depth[maxn],parent[maxlogn][maxn];
 40 int sum;
 41 
 42 inline void add_edge(int from,int to){
 43     edges[++cnt]=edge(to,head[from]);
 44     head[from]=cnt;
 45     edges[++cnt]=edge(from,head[to]);
 46     head[to]=cnt;
 47 }
 48 
 49 inline void add_ques(int a,int b,int c,int d){
 50     ques.push_back(make_pair(make_pair(a,b),make_pair(c,d)));
 51 }
 52 
 53 void getroot(int x,int fa){
 54     son[x]=1;  F[x]=0;
 55     for(int ee=head[x];ee;ee=edges[ee].next)
 56         if(edges[ee].to!=fa&&!vis[edges[ee].to]){
 57             getroot(edges[ee].to,x);
 58             son[x]+=son[edges[ee].to];
 59             F[x]=max(F[x],son[edges[ee].to]);
 60         }
 61     F[x]=max(F[x],sum-son[x]);
 62     if(F[x]<F[root])  root=x;
 63 }
 64 
 65 void dfs(int v,int fa,int deep){
 66     parent[0][v]=fa;
 67     depth[v]=deep;
 68     for(int ee=head[v];ee;ee=edges[ee].next)
 69         if(edges[ee].to!=fa)  dfs(edges[ee].to,v,deep+1);
 70 }
 71 
 72 void init(){
 73     memset(head,0,sizeof head);
 74     n=read(),q=read();
 75     for(int i=0;i<n-1;i++){
 76         int from=read(),to=read();
 77         add_edge(from,to);
 78     }
 79     for(int i=0;i<q;i++){
 80         int a=read(),b=read(),c=read(),d=read();
 81         add_ques(a,b,c,d);
 82     }
 83     memset(vis,0,sizeof vis);
 84     sum=F[root=0]=n;
 85     getroot(1,0);
 86     dfs(root,-1,0);
 87     for(int k=0;k+1<maxlogn;k++)
 88         for(int v=1;v<=n;v++)
 89             if(parent[k][v]<0)  parent[k+1][v]=-1;
 90             else  parent[k+1][v]=parent[k][parent[k][v]];
 91 }
 92 
 93 int lca(int u,int v){
 94     if(depth[u]>depth[v])  swap(u,v);
 95     for(int k=0;k<maxlogn;k++)
 96         if(depth[v]-depth[u]>>k&1)
 97             v=parent[k][v];
 98     if(u==v)  return u;
 99     for(int k=maxlogn-1;k>=0;k--)
100         if(parent[k][u]!=parent[k][v]){
101             u=parent[k][u];
102             v=parent[k][v];
103         }
104     return parent[0][u];
105 }
106 
107 bool check(PP qu){
108     int lca1=lca(qu.q1.ss,qu.q1.tt),lca2=lca(qu.q2.ss,qu.q2.tt);
109     if(depth[lca1]>=depth[lca2]&&(lca1==lca(qu.q2.ss,lca1)||lca1==lca(qu.q2.tt,lca1)))
110         return 1;
111     if(depth[lca2]>=depth[lca1]&&(lca2==lca(qu.q1.ss,lca2)||lca2==lca(qu.q1.tt,lca2)))
112         return 1;
113     return 0;
114 }
115 
116 void solve(){
117     for(int i=0;i<q;i++)
118         if(check(ques[i]))  puts("Y");
119         else  puts("N");
120 }
121 
122 int main(){
123     //freopen("temp.in","r",stdin);
124     init();
125     solve();
126     return 0;
127 }

就算孤岛已没有四季  也没人提及你的美丽  我还是要飞去那里
原文地址:https://www.cnblogs.com/ZYBGMZL/p/6868822.html