7-9 小字辈
1.题意
给定家族人口总数 N,家族成员从 1 到 N 编号,第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母,家谱中辈分最高的老祖宗对应的父/母编号为 -1。输出最小的辈分(老祖宗的辈分为 1,以下逐级递增),然后在第二行按递增顺序输出辈分最小的成员的编号。
2.题解
用vector数组存根与它的孩子,设祖宗的辈分是1,辈分越小辈分++,dfs更新最小辈分,搜到最小辈,塞进一个vector里。
3.代码
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int inf = 0x3f3f3f3f; 5 const int maxn = 1e5 + 5; 6 vector<int> descents[maxn], v; 7 int n, a, ancestor; 8 int maxdp = -1; 9 void dfs(int root, int dep) { 10 if(dep == maxdp) { 11 v.push_back(root); 12 } 13 14 if(dep > maxdp) { 15 maxdp = dep; 16 v.clear(); 17 v.push_back(root); 18 } 19 20 for(int i = 0; i<(int)descents[root].size(); i++) { 21 dfs(descents[root][i], dep + 1); 22 } 23 } 24 int main() { 25 scanf("%d", &n); 26 for(int i = 1; i <= n; i++) { 27 scanf("%d", &a); 28 if(a == -1) { 29 ancestor = i; 30 continue; 31 } 32 descents[a].push_back(i); 33 } 34 35 dfs(ancestor, 1); 36 sort(v.begin(), v.end()); 37 printf("%d\n", maxdp); 38 39 for(int i = 0; i < (int)v.size(); i++) { 40 if(i != 0) 41 printf(" "); 42 printf("%d", v[i]); 43 } 44 45 return 0; 46 }
7-11 互评成绩
1.题意
给定3个正整数,学生总数N、每份作业的评审数k、需要输出的学生数M,随后N行,每行给出一份作业得到的k个评审成绩,其间以空格分隔。每个人的作业会被k个同学评审,得到k个成绩。系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩。按非递减顺序输出最后得分最高的M个成绩,保留小数点后3位。
2.题解
模拟,把成绩塞到vector里即可,当时用的不熟,导致部分正确。
3.代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn = 1e5 + 5; 5 vector<double> v, ans; 6 bool cmp(double a, double b) { 7 return a > b; 8 } 9 int main() { 10 int n, k, m; 11 scanf("%d%d%d", &n, &k, &m); 12 13 for(int i = 1; i <= n; i++) { 14 double a[k + 1] = {0.0}; 15 for(int j = 1; j <= k; j++) { 16 scanf("%lf", &a[j]); 17 } 18 sort(a + 1, a + 1 + k); 19 double sum = 0.0; 20 for(int j = 2; j < k; j++) { 21 sum += a[j]; 22 } 23 double ans = sum / (double)(k - 2); 24 v.push_back(ans); 25 } 26 27 sort(v.begin(), v.end()); 28 int cnt = 0; 29 for(int i = (int)v.size() - 1; i >= 0; cnt++, i--) { 30 if(cnt == m) { 31 break; 32 } 33 ans.push_back(v[i]); 34 } 35 36 for(int i = (int)ans.size() - 1; i >= 0; i--) { 37 if(i == 0) { 38 printf("%.3f", ans[i]); 39 } else { 40 printf("%.3f ", ans[i]); 41 } 42 } 43 44 return 0; 45 }
7-12 深入虎穴
1.题意
情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门。每一扇门背后或者是一个房间,或者又有很多条路,同样是每条路通向一扇门,不存在两条路通向同一扇门,找出距离入口最远的那扇门。给定门的数量N,最后 N 行,第 i 行描述编号为 i 的那扇门背后能通向的门。在一行中输出距离入口最远的那扇门的编号。
2.题解
题目没给入口,需要把入口找到,没有哪扇门会通向入口,所以用vis数组记录每个门是否被通向,没被通向的那扇门就是入口,再用bfs搜到最深点。
3.代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn = 1e5 + 5; 5 int n; 6 vector<int> v[maxn]; 7 bool inq[maxn]; 8 bool vis[maxn]; 9 int level[maxn]; 10 int deepest; 11 int deepest_vertex; 12 void bfs(int s) { 13 queue<int> q; 14 q.push(s); 15 inq[s] = true; 16 level[s] = 1; 17 while(!q.empty()) { 18 int fro = q.front(); 19 q.pop(); 20 if(level[fro] > deepest) { 21 deepest = level[fro]; 22 deepest_vertex = fro; 23 } 24 25 for(int i = 0; i < v[fro].size(); i++) { 26 int u = v[fro][i]; 27 if(!inq[u]) { 28 level[u] = level[fro] + 1; 29 q.push(u); 30 inq[u] = true; 31 } 32 } 33 } 34 } 35 int main() { 36 scanf("%d", &n); 37 int k, x; 38 for(int i = 1; i <= n; i++) { 39 scanf("%d", &k); 40 for(int j = 0; j < k; j++) { 41 scanf("%d", &x); 42 vis[x] = true; 43 v[i].push_back(x); 44 } 45 } 46 for (int i = 1; i <= n; i++) { 47 if (!vis[i]) { 48 bfs(i); 49 } 50 } 51 cout << deepest_vertex; 52 53 return 0; 54 }