5 条题解

  • 15
    @ 2023-8-1 0:13:44

    对于这个问题,我们需要将员工按照一定规则划分为若干个组,使得在每个组内没有直接上下级的关系。题目要求形成的组数最少,因此我们可以采用深度优先搜索(DFS)的方法来解决。

    首先,我们可以用一个数组 f来表示每个员工的直接上级。数组中第 i 个元素的值 f[i] 表示第 i 个员工的直接上级编号。如果 f[i] 的值为 -1,则表示第 i 个员工没有直接上级,即是根节点。

    接下来,我们需要编写一个函数 dep(x, len) 来计算员工 x 的深度,其中 len 表示当前深度。如果员工 x 没有直接上级(即 f[x] == -1),则返回 len 作为最终深度;否则,递归调用 dep(f[x], len + 1) 来计算其直接上级的深度,并加1表示当前员工的深度。

    为了找到形成的组数最少,我们需要遍历所有员工,对每个员工调用 dep 函数计算其深度,并更新最大深度值 maxdep。最后,输出 maxdep 即为所求的答案。

    由于每个员工都需要调用 dep 函数计算深度,时间复杂度为 O(n^2)。对于较小的 n,这个复杂度是可以接受的。

    总结思路:

    1. 构建数组 f 表示每个员工的直接上级,其中 f[i] 表示第 i 个员工的直接上级编号。
    2. 编写函数 dep(x, len) 来计算员工 x 的深度,其中 len 表示当前深度。
    3. 遍历所有员工,对每个员工调用 dep 函数计算深度,并更新最大深度值 maxdep
    4. 输出 maxdep 即为形成的最少组数。

    PY

    def dep(x, f):
        if f[x] == -1:
            return 1
        return dep(f[x], f) + 1
    
    n = int(input())
    f = [-1] * (n + 1)
    
    for i in range(1, n + 1):
        f[i] = int(input())
    
    maxdep = 0
    
    for i in range(1, n + 1):
        maxdep = max(maxdep, dep(i, f))
    
    print(maxdep)
    

    C++:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int dep(int x, vector<int>& f) {
        if (f[x] == -1) {
            return 1;
        }
        return dep(f[x], f) + 1;
    }
    
    int main() {
        int n;
        cin >> n;
        
        vector<int> f(n + 1, -1);
        
        for (int i = 1; i <= n; i++) {
            cin >> f[i];
        }
        
        int maxdep = 0;
        
        for (int i = 1; i <= n; i++) {
            maxdep = max(maxdep, dep(i, f));
        }
        
        cout << maxdep << endl;
        
        return 0;
    }
    
    
    • @ 2023-8-7 23:38:57

      你会的还怪多的嘞

    • @ 2024-5-30 19:05:21

      /user/17413
      你的名字我要是打出来你可能会当场bi命

    • @ 2024-5-30 19:06:32

      /user/17413
      你的名字我要是打出来你可能会当场bi命

    • @ 2024-6-11 18:41:51

      http://oj.hetao101.com/d/extra_training/user/17413
      你的名字我要是打出来你可能会当场bi命

    • @ 2024-6-11 18:42:57

      /user/17413
      你的名字我要是打出来你可能会当场bi命(刚刚那三句打错了)。

    • @ 2024-6-11 18:43:46

      咦什么鬼,怎么艾特人

  • 9
    @ 2024-3-17 16:10:50

    点击查收题解

    题目描述

    P1070. 聚会

    一家公司有 n(1≤n≤2×103)(1n2×103) 名员工,从第 1** 人到第 n 人。每个员工要么没有直接经理,要么只有一个直接经理,后者是另一个具有不同编号的员工。如果以下情况中至少有一个是正确的,则称 A 雇员是 B 雇员的上级:

    雇员 A 是雇员 B 的直接经理。

    雇员 B 有一个直接经理雇员 C,雇员 A 是雇员 C 的上级。

    公司不存在管理循环,也就是说,不存在一个员工是他/她自己的上级。

    今天公司将安排一个聚会。这涉及到将所有 n 个雇员分为几个组:每个雇员必须恰好属于一个组。此外,在任何一个集团内,不得有两名雇员 A 和 B,满足 A 是 B 的上级。

    必须组成的组的最小数目是多少?

    输入格式

    第一行包含整数 n ( 1n2000 ) — 员工人数。

    接下来的 n 行包含整数 pi (1pinpi=1)。每个 pi 表示第 i 个员工的直接上级。如果pi = -1,则表示第 i 个员工没有直接上级。

    保证不会出现管理循环。

    输出格式

    输出一个整数,表示聚会中将形成的最少组数。

    思路

    本题中各个职员间有所属关系,并且没有管理循环,依此我们可以建立一棵树,最上级为根节点,最下级为子节点,定义deep数组储存每个人的深度,注意p可能为-1,而下标却不能为-1,所以把-1号人设为第0号人,所以p要与0求较大值,此时遍历求最大深度即可得出AC答案

    易错点

    在此种思路下,把第0号人当作所有人的上级,即根节点。但实际上并不存在第0号人,所以第0号的深度初始设置是0,定义成全局变量则无需初始化

    代码
    #include <bits/stdc++.h>
    using namespace std;
    vector<int> v[5000];
    int deep[5000];
    int ans;
    void dfs(int x)
    {
    	for (int i = 0;i < (int)v[x].size();i++)
    	{
    		deep[v[x][i]] = deep[x] + 1;
    		ans = max(ans,deep[v[x][i]]);
    		dfs(v[x][i]);
    	}
    }
    int main()
    {
    	int n,p;
    	cin >> n;
    	for (int i = 1;i <= n;i++)
    	{
    		cin >> p;
    		v[max(p,0)].push_back(i);
    	}
    	dfs(0);
    	cout << ans;
    	return 0;
    }
    

    累死了,只能问上一句,你点赞了吗?😵 V

    100 Accepted

    状态

    分数

    #1

    10

    #2

    10

    1ms

    7.6 MiB

    #3

    10

    0ms

    #4

    10

    1ms

    #5

    10

    1ms

    #6

    10

    1ms

    #7

    v

    10

    1ms

    #8

    10

    0ms

    #9

    10

    0ms

    7.6 MiB

    7.5 MiB

    7.4 MiB

    7.4 MiB

    7.8 MiB

    7.6 MiB

    7.5 MiB

    #10

    v Accepted

    v Accepted

    v Accepted

    v Accepted

    v Accepted

    V Accepted

    Accepted

    v Accepted

    v Accepted

    v Accepted

    耗时

    1ms

    内存占用

    7.6 MiB

    10

    1ms

    7.4 MiB

    • 1
      @ 2023-7-6 16:34:43

      根据题意,从任意节点到根的路径上的点,不能属于同一组。而不同路径上的点可以属于同一组。因此,最终答案就是深度最大的点的深度。由于本题的n比较小,可以接受O(n2)O(n^2)的时间复杂度,因此可以编写一个dep函数,递归求出每个点的深度。(使用dfs求深度也可以)

      核心代码
      
      for (int i = 1; i <= n; ++i)
          maxdep = max(maxdep, dep(i, 1));
      
      dep函数
      
      int dep(int x, int len)
      {
          if (f[x] == -1)
              return len;
          return dep(f[x], len + 1);
      }
      
      • -9
        @ 2024-4-5 19:22:22

        话不多说,直接上主要代码。

        vector<int> v[5000];
        int deep[5000];
        int ans;
        void dfs(int x)
        {
        	for (int i = 0;i < (int)v[x].size();i++)
        	{
        		deep[v[x][i]] = deep[x] + 1;
        		ans = max(ans,deep[v[x][i]]);
        		dfs(v[x][i]);
        	}
        }
        int main()
        {
        	int n,p;
        	cin >> n;
        	for (int i = 1;i <= n;i++)
        	{
        		cin >> p;
        		v[max(p,0)].push_back(i);
        	}
        	dfs(0);
        	cout << ans;
        

        你点赞了吗? 注:为你好,自己写头文件与返回值。

        • -11
          @ 2024-4-6 10:17:15

          AC代码

          #include <bits/stdc++.h> using namespace std; int dep(int x, vector < int > & f){ if (f[x] == -1) { return 1; } return dep(f[x], f) + 1; } int main() { int n; cin >> n ; vector < int > f(n + 1, -1); for (int i = 1; i <= n ; i ++) { cin >> f[i]; } int maxx = 0; for (int i = 1; i <= n ; i ++) { maxx = max(maxx , dep(i, f)); } cout << maxx; }

          • 1

          信息

          ID
          265
          时间
          1000ms
          内存
          256MiB
          难度
          2
          标签
          (无)
          递交数
          644
          已通过
          382
          上传者