zoukankan      html  css  js  c++  java
  • 2016 acm香港网络赛 B题. Boxes

    原题网址:https://open.kattis.com/problems/boxes

     

    Boxes

    There are N boxes, indexed by a number from 1 to N.Each box may (or not may not) be put into other boxes. These boxes together form a tree structure (or a forest structure, to be precise).

    You have to answer a series of queries of the following form: given a list of indices of the boxes, find the total number of boxes that the list of boxes actually contain.

    Consider, for example, the following five boxes.

    includegraphics[width=0.5	extwidth ]{Boxes}
    Figure 1: Sample input
    • If the query is the list “1”, then the correct answer is “5”, because box 1 contains all boxes.
    • If the query is the list “4 5”, then the correct answer is “2”, for boxes 4 and 5 contain themselves and nothing else.
    • If the query is the list “3 4”, then the correct answer is “2”.
    • If the query is the list “2 3 4”, then the correct answer is “4”, since box 2 also contains box 5.
    • If the query is the list “2”, then the correct answer is “3”, because box 2 contains itself and two other boxes.

    Input

    The first line contains the integer N (1≤N≤200000), the number of boxes.

    The second line contains N

    ­integers. The ith integer is either the index of the box which contains the ith box, or zero if the ith box is not contained in any other box.

    The third line contains an integer Q(1≤Q≤100000), the number of queries. The following Q lines will have the following format: on each line, the first integer M (1≤M≤20) is the length of the list of boxes in this query, then M integers follow, representing the indices of the boxes.

    Output

    For each query, output a line which contains an integer representing the total number of boxes.

    Sample Input 1              

       Sample Output 1

    5

    0 1 1 2 2

    5

    1 1

    2 4 5

    2 3 4

    3 2 3 4

    1 2

    5

    2

    2

    4

    3

     

     

    Author(s): Chan Pak Hay

    Source: Hong Kong Regional Online Preliminary 2016

    题意:n个箱子,其中一些箱子装在另一些里面。Q次询问,每次给定m个箱子,问这m个箱子里面一共包含了几个箱子(包括m个箱子本身)。

    建树,若第i个箱子装在第j个箱子里面,j为i的父节点。

    箱子编号1~n, 箱子组成树或者森林结构,确定一个根节点0,这样箱子组成的森林就合成一棵根节点为0的树。

    从根节点0开始DFS遍历整个树, 记录每个节点DFS到的顺序编号DFN[i].

    tot[i]表示箱子i包含的箱子总数(包括箱子i本身)。

    每个箱子包含的箱子的集合在DFS遍历的顺序下是连续的。

    range[i]表示箱子i包含的箱子的DFN编号范围,即DFN编号为range[i].first~range[i].second的所有箱子都包含在箱子i里面。

    举个例子,样例建树DFS遍历

                                                       

       其中,range[1].first=1,range[1].second=5; DFN编号为1~5的箱子都包含在箱子1中。

               range[2].first=2,range[2].second=4; DFN编号为2~4的箱子都包含在箱子4中。

               range[3].first=5,range[3].second=5;  DFN编号为5的箱子包含在箱子3中。

               range[4].first=3,range[4].second=3; DFN编号为3的箱子包含在箱子4中。

               range[5].first=4,range[5].second=4; DFN编号为4的箱子包含在箱子5中。

                                       

    得到了每个包含的箱子总数tot[i],和每个箱子i包含的箱子编号范围range[i],

    对于每一组查询q,暴力枚举一遍每个箱子q[i]是否被另一个箱子包含,如果q[i]被包含,删掉q[i],最后没删掉的节点的tot求和。

    #include <algorithm>
    #include <cstring>
    #include <string.h>
    #include <iostream>
    #include <list>
    #include <map>
    #include <set>
    #include <stack>
    #include <string>
    #include <utility>
    #include <vector>
    #include <cstdio>
    #include <cmath>
    
    #define LL long long
    #define N 200005
    #define INF 0x3ffffff
    
    using namespace std;
    
    int n;
    int belong[N];       //belong[i]表示箱子i在箱子elong[i]里面
    int qnum;             //查询次数
    int m;
    int q[25];
    vector<int>vec[N];
    
    int DFN[N];                       // 每个节点DFS到的顺序编号DFN[i]
    pair<int,int>range[N];     //range[i]表示箱子i包含的箱子的DFN编号范围
    int tot[N];                         //tot[i]表示箱子i包含的箱子总数(包括箱子i本身
    int pos;
    
    
    void dfs(int u)          //DFS遍历树
    {
        DFN[u]=pos++;
       range[u].first=pos;
        tot[u]=1;
        for(int i=0;i<vec[u].size();i++){
            int v=vec[u][i];
            dfs(v);
            tot[u]+=tot[v];
        }
        range[u].second=pos;
       return;
    }
    
    int main()
    {
       while(scanf("%d",&n)!=EOF){
        pos=0;
        memset(tot,0,sizeof(tot));
         for(int i=1;i<=n;i++) vec[i].clear();
    
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&belong[i]);
            vec[belong[i]].push_back(i);
        }
        dfs(0);     //从根节点0开始遍历
    
    /*
         for(int i=1;i<=n;i++)
            {
                cout<<tot[i]<<endl;
                cout<<DFN[i]<<endl;
                cout<<range[i].first<<' '<<range[i].second<<endl;
            }
      */
    
        scanf("%d",&qnum);
        while(qnum--)
        {
            scanf("%d",&m);
            for(int i=0;i<m;i++)
            {
                scanf("%d",&q[i]);         //q数组为查询的箱子集合
            }
            int flag=0;                       //用flag来记录哪些箱子被删掉了,如果(flag&(1<<i)),箱子q[i]就被删掉了。
            for (int i=0;i<m;i++)       //暴力枚举每个箱子q[i],看是否包含在另一个箱子里面
            {
                if(!(flag&(1<<i)))
                    {
                        for(int j=i+1;j<m;j++)
                        {
                            if(!(flag&(1<<j)))
                            {
                                if (range[q[i]].first<=range[q[j]].first && range[q[i]].second>=range[q[j]].second){          //箱子q[j]包含在箱子q[i]里面
                                    flag|=(1<<j);
                                    }
                                else if (range[q[j]].first<=range[q[i]].first && range[q[j]].second>=range[q[i]].second) {      //箱子q[i]包含在箱子q[j]里面
                                    flag|=(1<<i);
                                    break;
                                    }
                            }
                        }
                    }
            }
    
            int ret= 0;
            for (int i=0;i<m;i++)
            {
                if(!(flag&(1<<i)))  {     //箱子q[i]没被其他箱子包含
                        ret+=tot[q[i]];
                }
            }
    
            printf("%d
    ",ret);
        }
       }
        return 0;
    }
  • 相关阅读:
    (转+原)python中的浅拷贝和深拷贝
    (原)torch7中添加新的层
    (原+转)ubuntu终端输出彩色文字
    (原)torch中显示nn.Sequential()网络的详细情况
    (原)python中使用plt.show()时显示图像
    eclipse 注释模板
    leetcode 11 最大盛水容器
    leetcode 9 回文数字
    leetcode8 字符串转整数
    利用Intent启动activity的例子
  • 原文地址:https://www.cnblogs.com/smartweed/p/5860808.html
Copyright © 2011-2022 走看看