zoukankan      html  css  js  c++  java
  • 466E

    这题说的是给了一个公司员工100000 然后现在又3种操作第一种将y置为x的父亲,第二种操作将文件给第x个人签他签完给他的上司签,一直到没有上司为止,第三种操作问x是否签了第i份文件,然后 我们只要直到每两个点在最后形成的这颗树的位置只有祖先关系第一类   叔叔兄弟和其他的归为另一类,然后我们通过并查集判断他们是否在同一颗树中如果在判断他们的关系可以用刚刚处理出来的关系

    处理这个关系用的是 访问的时间差可以判断是否为这个节点的孩子 看下面的代码 tin[x]<=tin[y]&&tou[x]>=tou[y] 那么y一定是x的孩子或者是x

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn =100005;
    int tin[maxn],tou[maxn];
    int tag[maxn];
    vector<int>F[maxn];
    int op[maxn],x[maxn],y[maxn];
    int qusetion[maxn],time;
    vector<int>ansquestion[maxn];
    void dfs(int v, int p=-1){
         tin[v]=time++;
         int L=F[v].size();
         for(int i=0; i<L; ++i){
             int to = F[v][i];
             if(to==p) continue;
             dfs(to,v);
         }
         tou[v]=time++;
    }
    int per[maxn];
    int fa(int a){
       return per[a]= a==per[a]?a:fa(per[a]);
    }
    void unin(int a, int b){
         a=fa(a); b=fa(b);
         if(a!=b) per[a]=b;
    }
    bool ans[maxn];
    int paatt(int a,int b){
        return tin[a]<=tin[b]&&tou[a]>=tou[b];
    }
    int main()
    {
         memset(ans,false,sizeof(ans));
         int n,m,number=0;
         scanf("%d%d",&n,&m);
         for(int i=0; i<m; ++i){
              scanf("%d",&op[i]);
              if(op[i]==2){
                 scanf("%d",&x[i]);
              }else scanf("%d%d",&x[i],&y[i]);
              if(op[i]==1){
                   F[y[i]].push_back(x[i]);
                   tag[x[i]]++;
              }else if(op[i]==2){
                   qusetion[i]=++number;
              }else {
                    ansquestion[y[i]].push_back(i);
              }
         }
         time=1;
         for(int i=1; i<=n; ++i){
            if(tag[i]!=0||tin[i]!=0) continue;
            dfs(i);
         }
         for(int i=1; i<=n; ++i)
            per[i]=i;
    
         for(int i=0; i<m; ++i){
              if(op[i]==1){
    
                 unin(x[i],y[i]);
              }else if(op[i]==2){
                   int an= qusetion[i];
                   int root=x[i];
                   int L = ansquestion[an].size();
                   for(int j=0; j<L; ++j){
                       int  to = ansquestion[an][j];
                       int  in=x[to];
                       ans[to]=fa(in)==fa(root)&&paatt(in,root);
                   }
              }
         }
         for(int i=0; i<m; ++i)
             if(op[i]==3)
              printf("%s
    ",ans[i]?"YES":"NO");
        return 0;
    }
    View Code
  • 相关阅读:
    利用 PHP 导出 Git 某个分支下,新增或修改过的文件
    [翻译] 10 个实用的 Git 高级命令
    Django web project
    install virtualenv
    js原型继承
    HTML 学习杂记
    IDEA 文件列表隐藏某后缀文件
    coocsCreator杂记
    mac install brew
    c编程:输入一个数字n,则n代表n行,每行输入2个数字a,b计算每行的a+b问题。
  • 原文地址:https://www.cnblogs.com/Opaser/p/4001138.html
Copyright © 2011-2022 走看看