zoukankan      html  css  js  c++  java
  • Codeforces Round #417 (Div. 2) D. Sagheer and Kindergarten(树中判祖先)

    http://codeforces.com/contest/812/problem/D

    题意:

    现在有n个孩子,m个玩具,每次输入x y,表示x孩子想要y玩具,如果y玩具没人玩,那么x就可以去玩,如果y有人玩的话,x就必须等待y玩完后才能玩。如果出现循环,那么这个循环里的孩子都会哭。

    现在有q次询问,如果加入x y,会有多少孩子哭。

    思路:

    建立一棵树,根结点就是第一个玩玩具y的人,它的子树就是等待玩具的人(子树按照等待顺序建树)。这样就会形成很多棵树。

    这样的话,对于每个询问,我们去找到最后一个玩y玩具的人,只有y玩完了那才会给x,那么这样的话这两个人也应该连一条边,如果连边后形成了环,那么这个环里的顶点数就是哭的孩子数。

    其实这就是判断祖先的问题,如果x是最后一个玩y玩具的人的祖先,那么他们连边后肯定是要形成环的。

    那么怎么判断两个点的祖先关系呢?

    对树dfs,记录每个顶点的访问次序标号in和结束访问标号out,如果x是y的祖先就需要满足in【i】<in【y】<out【i】

    在这道题目中每个人最多只会等待一个玩具,所以在树中,每个结点最多只有一个子节点,那么我们就可以根据out和in标记来计算环中的顶点个数。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<sstream>
     6 #include<vector>
     7 #include<stack>
     8 #include<queue>
     9 #include<cmath>
    10 #include<map>
    11 using namespace std;
    12 typedef long long ll;
    13 typedef pair<int,long long> pll;
    14 const int INF = 0x3f3f3f3f;
    15 const int maxn=1e5+5;
    16 
    17 int n,m,k,q;
    18 vector<int> g[maxn];
    19 int in[maxn],out[maxn];
    20 int vis[maxn];
    21 int dfs_clock;
    22 
    23 //记录访问标记和结束标记
    24 void dfs(int u)
    25 {
    26     in[u]=++dfs_clock;
    27     for(int i=0;i<g[u].size();i++)
    28     {
    29         dfs(g[u][i]);
    30     }
    31     out[u]=dfs_clock;
    32 }
    33 
    34 int main()
    35 {
    36     //freopen("input.txt","r",stdin);
    37     scanf("%d%d%d%d",&n,&m,&k,&q);
    38     for(int i=1;i<=k;i++)
    39     {
    40         int x,y;
    41         scanf("%d%d",&x,&y);
    42         if(vis[y])
    43         {
    44             g[vis[y]].push_back(x);  //x需要等待,vis[y]玩好后给x
    45         }
    46         vis[y]=x;
    47     }
    48     dfs_clock=0;
    49     for(int i=1;i<=n;i++)
    50     {
    51         if(!in[i])
    52             dfs(i);
    53     }
    54 
    55     while(q--)
    56     {
    57         int x,y;
    58         scanf("%d%d",&x,&y);
    59         y=vis[y];  //找到最后一个玩y的人
    60         if(in[x]<=in[y] && out[x]>=in[y])
    61             printf("%d
    ",out[x]-in[x]+1);
    62         else
    63             puts("0");
    64     }
    65 
    66     return 0;
    67 }
  • 相关阅读:
    MongoDB 学习笔记(七):主从复制与副本集
    MongoDB 学习笔记(六):备份与用户管理
    MongoDB 学习笔记(五):固定集合、GridFS文件系统与服务器端脚本
    MongoDB 学习笔记(四):索引
    MongoDB 学习笔记(三):分页、排序与游标
    MongoDB 学习笔记(一):安装及简单shell操作
    MongoDB 学习笔记(二):shell中执行增删查改
    mongoDB 入门指南、示例
    mongoDB 介绍(特点、优点、原理)
    企业级任务调度框架Quartz(7) 线程在Quartz里的意义(1)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6984432.html
Copyright © 2011-2022 走看看