PTA甲级—树
1.树的遍历
1004 Counting Leaves (30分)
基本的数据结构——树,复习了链式前向星,bfs遍历判断即可


#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <cmath>
#define ll long long
#define inf 0x3f3f3f
#define pii pair<int, int>
using namespace std;
const int maxn = 1e4+100;
int n, m, k, par, child;
int cnt, head[maxn];
int level, ans[maxn];
struct node{
int to, nxt;
}e[maxn]; void add(int u, int v){
e[++cnt].nxt = head[u];
e[cnt].to = v;
head[u] = cnt;
}
void bfs(){
queue<pii> que;
que.push({1, 0});
while(!que.empty()){
pii tmp = que.front(); que.pop();
int u = tmp.first, step = tmp.second;
level = max(level, step);
if(head[u]){
for(int i = head[u]; i; i = e[i].nxt)
que.push({e[i].to, step+1});
}
else ans[step]++;
}
}
int main(){
scanf("%d%d", &n, &m);
while(m--){
scanf("%d%d", &par, &k);
while(k--){
scanf("%d", &child);
add(par, child);
}
}
bfs();
for(int i = 0; i <= level; i++){
printf("%d", ans[i]);
if(i!=level) printf(" ");
}
}
1053 Path of Equal Weight (30分)
树的遍历,需要思考的点在于如何记录路径并且排序输出


#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
#include <vector>
#include <set>
#define ll long long
#define inf 0x3f3f3f
#define pii pair<int, int>
#define pb push_back
using namespace std;
const int maxn = 1e4+100;
int n, m, s, cnt;
int val[maxn], fa[maxn];
int t, head[maxn];
vector<int> path[maxn];
struct node{
int to, nxt;
}e[maxn];
//bool cmp(vector<int> a, vector<int> b){
// reverse(a.begin(), a.end());
// reverse(b.begin(), b.end());
// return
//}
void add(int u, int v){
e[++t].to = v;
e[t].nxt = head[u];
head[u] = t;
}
void dfs(int u, int sum){
if(!head[u]&&sum==s) {
while(u!=-1) path[cnt].pb(val[u]), u = fa[u];
reverse(path[cnt].begin(), path[cnt].end());
cnt++;
}
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
if(v==fa[u]) continue;
dfs(v, sum+val[v]);
}
}
int main(){
scanf("%d%d%d", &n, &m, &s);
for(int i = 0; i <= n-1; i++) scanf("%d", &val[i]);
fa[0] = -1;
while(m--){
int u, v, k;
scanf("%d%d", &u, &k);
while(k--){
scanf("%d%", &v);
add(u, v), fa[v] = u;
}
}
dfs(0, val[0]);
sort(path, path+cnt);
for(int i = cnt-1; i >= 0; i--) {
int len = path[i].size();
for(int j = 0; j < len; j++)
cout << path[i][j] << (j==len-1 ? "" : " ");
cout << endl;
}
}
Reference:
https://www.cnblogs.com/vranger/p/3502885.html
1079 Total Sales of Supply Chain (25 分)
树的遍历,不过需要特别注意每次利润点是r%而不是r


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int maxn = 1e5+100;
int n;
ll num[maxn];
double p, r, ans;
int head[maxn], t;
struct node{
int to, nxt;
}e[maxn];
void add(int u, int v){
e[++t] = {v, head[u]};
head[u] = t;
}
void dfs(int u, double pri){
if(head[u]==0) ans += pri*num[u];
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
dfs(v, pri*(1+r*0.01));
}
}
int main(){
scanf("%d%lf%lf", &n, &p, &r);
for(int u = 0; u < n; u++){
int m, v;
scanf("%d", &m);
if(m==0) scanf("%lld", &num[u]);
while(m--){
scanf("%d", &v);
add(u, v);
}
}
dfs(0, p);
printf("%.1lf", ans);
}
1090 Highest Price in Supply Chain (25 分)
树的遍历,应当仔细审题,要求拥有最大销售价格的零售商数目,而不是编号


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std;
const int maxn = 1e5+100;
int n, s;
ll cnt, num[maxn];
double p, r, ans;
int head[maxn], t;
struct node{
int to, nxt;
}e[maxn];
void add(int u, int v){
e[++t] = {v, head[u]};
head[u] = t;
}
void dfs(int u, double pri){
if(head[u]==0) {
if(ans==pri) cnt++;
else if(ans<pri) ans = pri, cnt = 1;
}
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
dfs(v, pri*(1+r*0.01));
}
}
int main(){
scanf("%d%lf%lf", &n, &p, &r);
for(int u = 0; u < n; u++){
int m, v;
scanf("%d", &v);
if(v==-1) s = u;
else add(v, u); }
dfs(s, p);
printf("%.2lf %d", ans, cnt);
}
1106 Lowest Price in Supply Chain (25 分)
树的遍历,和前两题是一个系列的,代码稍作修改即可


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+100;
int n, s, cnt;
ll num[maxn];
double p, r, ans = 1e10+100;
int head[maxn], t;
struct node{
int to, nxt;
}e[maxn];
void add(int u, int v){
e[++t] = {v, head[u]};
head[u] = t;
}
void dfs(int u, double pri){
if(head[u]==0) {
if(ans==pri) cnt++;
else if(ans>pri) ans = pri, cnt = 1;
}
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
dfs(v, pri*(1+r*0.01));
}
}
int main(){
scanf("%d%lf%lf", &n, &p, &r);
for(int u = 0; u < n; u++){
int m, v;
scanf("%d", &m);
while(m--){
scanf("%d", &v);
add(u, v);
}
}
dfs(0, p);
printf("%.4lf %d", ans, cnt);
}
1094 The Largest Generation (25 分)
树的遍历,简直是个大水题


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+100;
int n, m;
int resLev, maxLev, res, cnt[maxn];
int head[maxn], t;
struct node{
int to, nxt;
}e[maxn];
void add(int u, int v){
e[++t] = {v, head[u]};
head[u] = t;
}
void dfs(int u, int lev){
cnt[lev]++, maxLev = max(maxLev, lev);
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
dfs(v, lev+1);
}
}
int main(){
scanf("%d%d", &n, &m);
while(m--){
int u, v, num;
scanf("%2d %d", &u, &num);
while(num--){
scanf("%d", &v);
add(u, v);
}
}
dfs(1, 1);
for(int i = 1; i <= maxLev; i++)
if(res<cnt[i]) resLev = i, res = cnt[i];
printf("%d %d", res, resLev);
}
2.二叉查找树
1043 Is It a Binary Search Tree (25 分)
一种方法是用给出的输入构造出一棵二叉搜索树,然后再对这棵树进行前序遍历,判断得到的结果是否和输入一致,如果不一致,那就输出 NO,如果一致就输出这这棵树的后序遍历结果。


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, data;
vector<int> orgin, pre, preMir, post, postMir;
struct node{
int data;
node *lch, *rch;
};
//构建BST,需要加&
void insert(node* &root, int data){
if(root==NULL){
root = new node;
root->data = data;
root->lch = root->rch = NULL;
return;
}
if(data<root->data) insert(root->lch, data);
else insert(root->rch, data);
}
void preOrder(node *root){
if(root!=NULL){
pre.pb(root->data);
// printf("%d ", root->data);
preOrder(root->lch);
preOrder(root->rch);
}
}
void preMirOrder(node *root){
if(root!=NULL){
preMir.pb(root->data);
preMirOrder(root->rch);
preMirOrder(root->lch);
}
}
void postOrder(node *root){
if(root!=NULL){
postOrder(root->lch);
postOrder(root->rch);
post.pb(root->data);
}
}
void postMirOrder(node *root){
if(root!=NULL){
postMirOrder(root->rch);
postMirOrder(root->lch);
postMir.pb(root->data);
}
}
void test(){
for(int i = 0; orgin[i]; i++) {
printf("%d", orgin[i]);
if(i!=orgin.size()-1) printf(" ");
else printf("\n");
}
for(int i = 0; pre[i]; i++) {
printf("%d", pre[i]);
if(i!=pre.size()-1) printf(" ");
else printf("\n");
}
}
int main(){
scanf("%d", &n);
node *root = NULL;
while(n--){
scanf("%d", &data);
orgin.pb(data);
insert(root, data);
}
preOrder(root);
preMirOrder(root);
// test();
if(orgin==pre){
printf("YES\n");
postOrder(root);
int len = post.size();
for(int i = 0; i < len; i++) {
printf("%d", post[i]);
if(i!=len-1) printf(" ");
}
}
else if(orgin==preMir){
printf("YES\n");
postMirOrder(root);
int len = postMir.size();
for(int i = 0; i < len; i++) {
printf("%d", postMir[i]);
if(i!=len-1) printf(" ");
}
}
else printf("NO\n"); }
Method 1
另一种方法是假设这个输入序列是对的,然后利用这个输入序列去得到后序序列并保存,如果最终得到的结果中节点个数不够(这种情况下部分节点不会被遍历到,e.g 8 6 8 5 10 9 11),那说明它不是正确的前序遍历,否则就直接输出得到的结果。这种方法基于以下前提:
一般情况下,我们要根据一棵二叉树的前序遍历结果和中序遍历结果才能得到它的后序遍历结果。但由于这里是BST,因此根据左子树所有节点的键值小于根节点这个特点就可以划分左右子树进行遍历,从而得出后序遍历结果


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n;
bool isMirror;
vector<int> pre, post;
void getpost(int root, int tail){
if(root>tail) return;
int i = root + 1, j = tail;
if(isMirror){
while(i<=tail&&pre[i]<pre[root]) i++;
while(j>=root+1&&pre[j]>=pre[root]) j--;
}
else{
while(i<=tail&&pre[i]>=pre[root]) i++;
while(j>=root+1&&pre[j]<pre[root]) j--;
}
getpost(root+1, j);
getpost(i, tail);
post.pb(pre[root]);
}
int main(){
scanf("%d", &n);
pre.resize(n);//使用vector输入数据要预先分配内存
for(int i = 0; i <= n-1; i++) scanf("%d", &pre[i]);
getpost(0, n-1);
if(post.size()!=n){
isMirror = true, post.clear();
getpost(0, n-1);
}
if(post.size()==n){
printf("YES\n%d", post[0]);
for(int i = 1; i <= n-1; i++)
printf(" %d", post[i]);
}
else printf("NO\n"); }
Method 2
Reference:
树的前序、中序、后续遍历(以根节点的访问顺序为界定):
https://www.cnblogs.com/wizarderror/p/10816635.html
如何唯一确定一棵二叉树&&先序遍历和后序遍历为什么不能唯一地确定一棵二叉树?(最简单的办法:反证法)
https://www.zybang.com/question/fc1b72ae09eadcb6b95ffbf2e675e432.html
https://www.nowcoder.com/questionTerminal/e77e06b71aa548ed8aefd030edb9b4a2
https://blog.csdn.net/chaoyue1216/article/details/7609689
https://zhuanlan.zhihu.com/p/73438175(见评论)
题解:
https://www.cnblogs.com/codervivi/p/13126320.html(推荐)
https://blog.csdn.net/qq_41528502/article/details/104389771
https://www.liuchuo.net/archives/2153
1099 Build A Binary Search Tree (30 分)
BST的中序遍历我们可以通过排序来得到,由此遍历二叉树时加上节点所在层数的信息,我们就能得出层次遍历的序列,最后输出即可


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, t, val[105], maxDepth;
vector<int> g[105], lev[105];
void dfs(int u, int dep){
if(u==-1) return;
maxDepth = max(maxDepth, dep);
dfs(g[u][0], dep+1);
lev[dep].pb(val[t++]);
dfs(g[u][1], dep+1);
}
int main(){
scanf("%d", &n);
for(int i = 0; i <= n-1; i++){
int u, v;
scanf("%d%d", &u, &v);
g[i].pb(u), g[i].pb(v);
}
for(int i = 0; i <= n-1; i++) scanf("%d", &val[i]);
sort(val, val+n), dfs(0, 0);
for(int i = 0; i <= maxDepth; i++){
for(int j = 0; j < lev[i].size(); j++){
printf("%d", lev[i][j]);
if(i==maxDepth&&j==lev[i].size()-1) continue;
else printf(" ");
} }
}
1064 Complete Binary Search Tree (30 分)
1099的完全二叉树版本。使用数组来存放完全二叉树,对于某一结点u, 其左右孩子的编号分别为2*u和2*u+1(根节点为1),观察易发现数组会按照层序来存放完全二叉树的n个节点。


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, t, val[1005], tree[1005];
void dfs(int u, int dep){
if(u>n) return;
dfs(2*u, dep+1);
tree[u] = val[++t];
dfs(2*u+1, dep+1);
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &val[i]);
sort(val+1, val+1+n), dfs(1, 0);
printf("%d", tree[1]);
for(int i = 2; i <= n; i++) printf(" %d", tree[i]);
}
3.二叉树的遍历
1020 Tree Traversals (25 分)
利用后序遍历和中序遍历来构建二叉树,按照两种序列的特性递归划分子树,由此来确定节点即可


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, post[maxn], in[maxn], maxDep;
vector<int> lev[maxn];
void dfs(int l1, int r1, int l2, int r2, int dep){
if(l1>r1||l2>r2) return;
int now = l2, dis;
for(int i = l2; i <= r2; i++)
if(in[i]==post[r1]) now = i;
lev[dep].pb(in[now]), maxDep = max(maxDep, dep);
dis = now-l2;
dfs(l1, l1+dis-1, l2, l2+dis-1, dep+1);
dfs(l1+dis, r1-1, l2+dis+1, r2, dep+1);
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &post[i]);
for(int i = 1; i <= n; i++) scanf("%d", &in[i]);
dfs(1, n, 1, n, 0);
for(int i = 0; i <= maxDep; i++)
for(int j = 0; j < lev[i].size(); j++){
printf("%d", lev[i][j]);
if(i==maxDep&&j==lev[i].size()-1) continue;
else printf(" ");
} }
1086 Tree Traversals Again (25 分)
首先要明确一点:先序、中序和后序遍历过程,其经过节点的路线一样,只是访问节点的时机不一样
这里Push的次序我们可以看作是先序遍历,Pop按照题意为中序遍历,于是问题就转化成了如何由先序遍历和中序遍历求后续遍历
最后注意处理输入即可


#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, val;
int pre[maxn], t1, in[maxn], t2, post[maxn], t3;
int t, sta[maxn];
string str;
void dfs(int l1, int r1, int l2, int r2){
if(l1>r1) return;
int now = l2, dis;
for(int i = l2; i <= r2; i++)
if(in[i]==pre[l1]) now = i;
dis = now-l2;
dfs(l1+1, l1+1+dis-1, l2, l2+dis-1);
dfs(l1+1+dis, r1, l2+dis+1, r2);
post[++t3] = in[now];
}
int main(){
scanf("%d", &n);
int time = 2*n;
while(time--){
cin >> str;
if(str=="Push"){
scanf("%d", &val);
pre[++t1] = sta[++t] = val;
}
else in[++t2] = sta[t--];
}
dfs(1, n, 1, n);
printf("%d", post[1]);
for(int i = 2; i <= t3; i++) printf(" %d", post[i]);
}
1102 Invert a Binary Tree (25 分)
An inversion, or mirror, of a Binary Tree (T), is just a Binary Tree M(T) whose left and right children (of all non-leaf nodes) are swapped.
按题目要求模拟即可,注意题目中名词的概念和数据输入


#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, maxDep;
int in[maxn], t;
vector<int> g[maxn], lev[maxn];
bool vis[maxn];
void dfs(int u, int dep){
if(u==-1) return;
dfs(g[u][0], dep+1);
in[++t] = u;
lev[dep].pb(u), maxDep = max(maxDep, dep);
dfs(g[u][1], dep+1);
}
int main(){
scanf("%d", &n);
for(int i = 0; i <= n-1; i++){
char u, v;
scanf(" %c %c", &u, &v);
v=='-' ? g[i].pb(-1) : g[i].pb(v-'0'), vis[v-'0'] = 1;
u=='-' ? g[i].pb(-1) : g[i].pb(u-'0'), vis[u-'0'] = 1;
}
for(int i = 0; i <= n-1; i++)
if(!vis[i]) dfs(i, 1);
for(int i = 1; i <= maxDep; i++)
for(int j = 0; j < lev[i].size(); j++){
printf("%d", lev[i][j]);
if(i==maxDep&&j==lev[i].size()-1) continue;
else printf(" ");
}
printf("\n%d", in[1]);
for(int i = 2; i <= n; i++) printf(" %d", in[i]);
}
4.平衡二叉树
1066. Root of AVL Tree (25)
泛泛的了解了下AVL树,看了慕课上视频和一些Wiki资料、博客啥的,当然还有些Splay、Treap、红黑树等等。目前不打算深入,一是没有对应的应用场景去驱动;二是要是以考证为目的来说,这些知识点有点小复杂,掌握需要花费过多的时间和精力而PAT不常考。
对AVL树的旋转操作感性理解就是:要使树达到平衡,其左右子树大小分布要尽可能的均匀,由于是二叉搜索树所以让中位数或者其附近的数作为根节点是个不错的选择。当其平衡性遭到破坏的时候,通过选取更合理的根节点来达到重新平衡的目的,旋转操作就是用尽可能简单的方法达到这个效果,四种不同的旋转操作只是对节点插入的位置做了分类讨论而已。
这道题目直接套用AVL树基本操作的模板即可


#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, val;
struct node{
int val;
node *lch, *rch;
};
int getHeight(node* root){
if(root==NULL) return 0;
return max(getHeight(root->lch), getHeight(root->rch))+1;
}
node* rotateLeft(node* root){
node* now = root->rch;
root->rch = now->lch;
now->lch = root;
return now;
}
node* rotateRight(node* root){
node* now = root->lch;
root->lch = now->rch;
now->rch = root;
return now;
}
node* rotateLeftRight(node* root){
root->lch = rotateLeft(root->lch);
return rotateRight(root);
}
node* rotateRightLeft(node* root){
root->rch = rotateRight(root->rch);
return rotateLeft(root);
}
void insert(node* &root, int val){
if(root==NULL){
root = new node;
root->val = val;
root->lch = root->rch = NULL;
return;
}
if(val<root->val){
insert(root->lch, val);
if(getHeight(root->lch)-getHeight(root->rch)==2)
root = val < root->lch->val ? rotateRight(root) : rotateLeftRight(root);
}
else{
insert(root->rch, val);
if(getHeight(root->lch)-getHeight(root->rch)==-2)
root = val >= root->rch->val ? rotateLeft(root) : rotateRightLeft(root);
}
}
int main(){
scanf("%d", &n);
node* root = NULL;
while(n--){
scanf("%d", &val);
insert(root, val);
}
printf("%d", root->val);
}
Reference:
AVL树:
https://blog.csdn.net/qq_25343557/article/details/89110319
https://en.wikipedia.org/wiki/AVL_tree
https://www.tutorialspoint.com/data_structures_algorithms/avl_tree_algorithm.htm
题解:
https://www.liuchuo.net/archives/2178(柳婼确实写的很不错)
5.堆
1098 Insertion or Heap Sort (25 分)
这题主要考察的是堆这种数据结构,又去把浙大数据结构的慕课看了看,解出此题需要掌握堆的概念及其各种操作,还有排序相关知识
此外,最后提交的时候测试样例2段错误
对于插入排序的下一次迭代的位置,得从前往后找,不能从后往前找
否则测试样例2错误。
例如:
4
3 4 2 1
3 4 2 1
-----------
正确答案:
Insertion Sort
2 3 4 1


#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, a[maxn], b[maxn];
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
if(b[1]<=b[2]){
printf("Insertion Sort\n");
// int p = n;
// while(a[p]==b[p]) p--;
int p = 1;
while(b[p+1]>=b[p]) p++;
sort(b+1, b+1+p+1);
}
else{
printf("Heap Sort\n");
int p = n, par, child, tmp;
while(b[p]>=b[0]&&b[p-1]<=b[p]) p--;
swap(b[1], b[p--]), tmp = b[1];
for(par = 1; par*2 <= p; par = child){
child = par*2;
if(child!=p&&b[child]<b[child+1]) child++;
if(tmp>=b[child]) break;
else b[par] = b[child];
}
b[par] = tmp;
}
printf("%d", b[1]);
for(int i = 2; i <= n; i++) printf(" %d", b[i]);
}
Reference:
堆&排序:
Code:
借鉴mooc&&柳婼
https://blog.csdn.net/liuchuo/article/details/52252172
debug:
https://blog.csdn.net/njtechlcj/article/details/105400209
https://blog.csdn.net/ever_promise/article/details/107567183
6.并查集
1107 Social Clusters (30 分)
并查集的基本操作,需要注意读懂题目的意思:
有n个人,每个人喜欢k个活动,如果两个人有任一活动相同,就认为他们处于同一个社交网络。求这n个人一共形成了多少个社交网络


#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e4+100;
int n, m, h, tot, f[maxn], cnt[maxn];
int t, hobby[maxn];
bool vis[maxn];
vector<int> g[maxn];
int find(int x){
if(f[x]!=x) f[x] = find(f[x]);
return f[x];
}
void merge(int x, int y){
x = find(x), y = find(y);
f[x] = y;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
f[i] = i;
scanf("%d:", &m);
while(m--){
scanf("%d", &h);
g[h].pb(i);
if(!vis[h]) hobby[++t] = h, vis[h] = 1;
}
}
for(int i = 1; i <= t; i++){
h = hobby[i];
for(int j = 1; j < g[h].size(); j++){
if(find(g[h][0])!=find(g[h][j])) merge(g[h][0], g[h][j]);
}
}
for(int i = 1; i <= n; i++) cnt[find(i)]++;
for(int i = 1; i <= n; i++)
if(cnt[i]!=0) tot++;
sort(cnt+1, cnt+1+n);
printf("%d\n%d", tot, cnt[n]);
for(int i = n-1; i >= n-tot+1; i--) printf(" %d", cnt[i]);
}
PTA甲级—树的更多相关文章
- PTA甲级1094 The Largest Generation (25分)
PTA甲级1094 The Largest Generation (25分) A family hierarchy is usually presented by a pedigree tree wh ...
- PTA 7-3 树的遍历 (25分)
PTA 7-3 树的遍历 (25分) 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(≤30),是二叉树中结点 ...
- PTA 03-树1 树的同构 (25分)
题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/711 5-3 树的同构 (25分) 给定两棵树T1和T2.如果T1可以通过若干次左右 ...
- PTA L2-006 树的遍历-二叉树的后序遍历+中序遍历,输出层序遍历 团体程序设计天梯赛-练习集
L2-006 树的遍历(25 分) 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(≤),是二叉树中结点的 ...
- PAT甲级 树 相关题_C++题解
树 目录 <算法笔记>重点摘要 1004 Counting Leaves (30) 1053 Path of Equal Weight (30) 1079 Total Sales of S ...
- PTA 7-10 树的遍历(二叉树基础、层序遍历、STL初体验之queue)
7-10 树的遍历(25 分) 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(≤30),是二叉树中结点的个数 ...
- PTA甲级B1061 Dating
目录 B1061 Dating (20分) 题目原文 Input Specification: Output Specification: Sample Input: Sample Output: 生 ...
- [刷题] PTA 03-树1 树的同构
程序: 1 #include <stdio.h> 2 #define MaxTree 10 3 #define ElementType char 4 #define Tree int 5 ...
- PTA 甲级 1139
https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312 其实这道题目不难,但是有很多坑点! 首先数据 ...
- PAT 甲级 树专题小结
1.已知两个序链表建树 先序中序建树 PAT 1086 node *buildTree(vector<int>pre,vector<int>in,int pl,int pr,i ...
随机推荐
- [oeasy]python0035_ 整合shell编程_循环_延迟_清屏
整合shell编程 回忆上次内容 用\r 可以让输出位置回到行首 原位刷新时间 如果想要的是大字符效果 需要使用 figlet 但同时还希望能刷新 编辑 这可能吗? 建立脚本 我们得熟悉一下s ...
- Vue Axios二次封装
// axios二次封装 import axios from 'axios' import qs from 'qs' /*** *判断环境变量区分接口的默认地址 */ switch (process. ...
- ABC348
A link 这道题就先输出整个的\(oox\),再输出剩一个两个的. 点击查看代码 #include<bits/stdc++.h> using namespace std; int n; ...
- 关于构建一个可视化+code系统的思路
思路是有参考UE的现有功能,加之前的逻辑. 大概分为三个模块: 底层, 即native层 ,这一层实际上分为三个部分: 1.GUI层的解析,2.数据存储 3.Code的解析 这三部分关键在于他们 ...
- bloom效果
搜索 复制
- 【perl】01
1.环境搭建 -- 解释器 / 编译器 Perl 在 Window 平台上有 ActiveStatePerl 和 Strawberry Perl 编译器. ActiveState Perl和 Stra ...
- 【Mybatis-Plus】Spring整合 驼峰命名设置失效问题
查询时发现这个问题: DEBUG [main] - Creating a new SqlSession DEBUG [main] - SqlSession [org.apache.ibatis.ses ...
- 贝塔分布 beta分布的累积分布函数(CDF)计算 —— 如何使用二项式分布表示beta分布的概率累积函数
贝塔分布 beta分布的累积分布函数(CDF)的计算公式: 计算beta分布的累积分布函数(CDF)是需要计算积分的,但是最近发现另一种计算方法,即,使用二项式分布计算beta分布的概率累积函数. b ...
- TensorFlow图像预处理函数
预处理图像 文件名: cat.jpg 读取.打印图片 import matplotlib.pyplot as plt import tensorflow as tf import nump ...
- baselines算法库common/vec_env/util.py模块分析
util.py模块代码: """ Helpers for dealing with vectorized environments. """ ...