C. cltt的幸运数LCAtarjan

/*C: cltt的幸运数
Time Limit: 1 s      Memory Limit: 128 MB
Submit
Problem Description
一棵树有n个节点,共m次查询,查询a,b的最近公共祖先是否为好数?若好数的数目是幸运数,输出YES,否则输出NO。

好数:可以表示为2的指数幂。如:1, 2,4,8,16,32,……

幸运数就是素数。

Input
nn(nn表示节点数目,接下来n−1n−1行,每行两个整数 x,yx,y 其中xx是yy的父节点)

mm(表示查询数目,接下来mm行,每行两个整数a,ba,b)

(1≤n≤105,1≤m≤10)(1≤n≤105,1≤m≤10)
Output
YESYES or NONO
Sample Input
12
1 2
1 3
2 5
3 4
3 6
4 7
7 9
7 10
6 8
8 11
8 12
4
9 8
4 7
11 12
10 7
Sample Output
YES*/

#include<iostream>
 #include<string.h>
 #include<algorithm>
 using namespace std;
 struct node
 {
     int fa;
     bool vis;
 }p[100001];
 bool check(int x)
 {
     if(x==0||x==1)return 0;
     if(x==2)return 1;
     for(int i=2;i*i<=x;i++)
         if(x%i==0)
             return 0;
     return 1;
 }
 int lca(int x,int y)
 {
     p[x].vis=1;
     while(x!=p[x].fa)//往上遍历到0
     {
         p[x].vis=1;
         x=p[x].fa;
     }//printf("%d\n",x);
     while(y!=p[y].fa)//无公共祖先时y=0;
     {
         if(p[y].vis)
            break;
         y=p[y].fa;
     }//printf("%d\n", y);
     return y;
 }
 int main()
 {
     int n;
     scanf("%d",&n);
     for(int i=1;i<=n;i++)
        p[i].fa=0;
     for(int i=1;i<n;i++)
     {
         int x,y;
         scanf("%d%d",&x,&y);
         p[y].fa=x;
     }
     int o;
     int cnt=0;
     scanf("%d",&o);
     for(int i=0;i<o;i++)
     {
         int x,y;
         scanf("%d%d",&x,&y);
         for(int i=0;i<=100001;i++)
            p[i].vis=0;
         int ans=lca(x,y);
         if(!(ans&(ans-1)))//0是本题特例,一般情况写if(ans!=0&&!(ans&ans-1))
            cnt++;//printf("%d\n",cnt );
     }
     if(check(cnt))
        printf("YES\n");
    else
        printf("NO\n");
    return 0;
 }

 

posted @ 2018-08-14 21:44  aeipyuan  阅读(142)  评论(0编辑  收藏  举报