PAT (Advanced Level) Practice 题解代码 - III (1101-1150)

PAT

PAT (Advanced Level) Practice - III(1101-1150)

--------------------------------------------------------------------------------

1001-1167(已更新至最新!)

1101-1150

--------------------------------------------------------------------------------

更多详见>>

OJ题解系列 目录导航帖
--------------------------------------------------------------------------------

题目传送门

PAT (Advanced Level) Practice
--------------------------------------------------------------------------------

这里是PAT (Advanced Level) Practice - III(1101-1150)
这是一个全新的起点,我们完成了乙级考试的小目标,向着甲级考试的大目标前进,你将会看到一片新的世界,在数据结构和算法的大海里遨游
首先,我们讲讲两种考试的区别:
1.题面描述不同,乙级考试采用中文描述,甲级考试采用英文描述
2.题目数量不同,乙级考试是5道题,甲级考试是4道题
3.题目的分值不同,乙级考试的分值分布为15/20/20/20/25,甲级考试的分值分布为20/25/25/30
4.难度不同,甲级考试相对乙级考试来说会增加一个难度级别,主要体现在对数据结构的掌握上,如树和图——主要有BST/BBST/CBT/Heap/DAG,算法方面在原有的难度基础之上加深一点(比方说大模拟),引入了一些简单DP
知己知彼方能百战不殆,我们了解基本的区别之后,大家也不用太担心考试的难度问题,毕竟数据规模n不像竞赛要求那么高,很多算法用最普通的枚举方法往往也能取得满分!

接下来就是题解部分了,每道算法题都标注有对应的算法标签,对于那些易错、较难或是测试点比较特殊的题目会着重标注,本章推荐的题目有:

1102 Invert a Binary Tree (25 分)/
1106 Lowest Price in Supply Chain (25 分)
1110 Complete Binary Tree (25 分)
1115 Counting Nodes in a BST (30 分)
1123 Is It a Complete AVL Tree (30 分)
1135 Is It A Red-Black Tree (30 分)
树,二叉树 + DFS/BFS
1111 Online Map (30 分)
1131 Subway Map (30 分)
图论 + Dijkstra or DFS
1129 Recommendation System (25 分)模拟 + 排序
1139 First Contact (30 分)图论 + BFS

--------------------------------------------------------------------------------

1101 Quick Sort (25 分)

算法标签: 排序(枢轴选取)
注意点:
这道题目考察的知识点为快速排序的子算法——枢轴的选取,一个序列中,能成为枢轴的元素A必定是左边全部小于等于A而右边全部大于等于A的点!因此,直接遍历序列即可,复杂度O(n)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int minx[maxn] = {0};
int maxx[maxn] = {0};
int a[maxn];
const int maxnum = INT_MAX;
int b[maxn];
int main(){
	int N;
	cin >> N;
	for(int i=1;i<=N;i++){
		cin >> a[i];
	}
	minx[N+1] = maxnum;
	maxx[N+1] = maxnum;
	for(int i=1;i<=N;i++){
		maxx[i] = max(maxx[i-1],a[i]);
	}
	for(int i=N;i>=1;i--){
		minx[i] = min(minx[i+1],a[i]);
	}
	int cnt = 0;
	for(int i=1;i<=N;i++){
		if(a[i]>maxx[i-1] && a[i]<minx[i+1]){
			b[cnt++] = a[i];
		}
	}
	sort(b,b+cnt);
	cout << cnt << endl;
	for(int i=0;i<cnt;i++){
		if(i==cnt-1){
			cout << b[i];
		}else{
			cout << b[i] << " ";
		}
	}
	cout << endl;
	return 0;
}

1102 Invert a Binary Tree (25 分)

算法标签: 树,二叉树 + DFS + BFS
注意点:
1.反转二叉树只需交换左右子树即可
2.整体思路:建树,层序遍历,中序遍历
可参考P1021/P1053/P1079/P1086/P1090,解法相同

#include<bits/stdc++.h>
using namespace std;
struct node{
	int data;
	int lchild;
	int rchild;
};
node n[105];

int index_num = 0;
int newnode(int v){
	n[index_num].data = v;
	n[index_num].lchild = -1;
	n[index_num].rchild = -1;
	return index_num++;
}

bool hashT[105];
int cnt1 = 0;
int cnt2 = 0;
void Level(int root){
	queue<int> q;
	q.push(root);
	while(!q.empty()){
		int f = q.front();
		if(cnt1==0){
			printf("%d",f);
		}else{
			printf(" %d",f);
		}
		cnt1++;
		q.pop();
		if(n[f].lchild!=-1){
			q.push(n[f].lchild);
		}
		if(n[f].rchild!=-1){
			q.push(n[f].rchild);
		}
	}
	printf("\n");
}
void InOrder(int root){
	if(root==-1){
		return;
	}
	InOrder(n[root].lchild);
	if(cnt2==0){
		printf("%d",root);
	}else{
		printf(" %d",root);
	}
	cnt2++;
	InOrder(n[root].rchild);
}
int main(){
	int N;
	cin >> N;
	for(int i=0;i<N;i++){
		string s1,s2;
		cin >> s1 >> s2;
		int now = newnode(i);
		if(s1[0]!='-'){
			n[now].rchild = s1[0]-'0';
			hashT[s1[0]-'0'] = true;
		}
		if(s2[0]!='-'){
			n[now].lchild = s2[0] -'0';
			hashT[s2[0]-'0'] = true;
		}
	}
	int root;
	for(int i=0;i<N;i++){
		if(!hashT[i]){
			root = i;
			break;
		}
	}
	Level(root);
	InOrder(root);
	
	return 0;
}

1103 Integer Factorization (30 分)

算法标签: DFS
注意点: 本题是一道DFS模板题,DFS搜索过程中,需要当前因子和factor_sum,数字和sum以及当前的选取数字

#include<bits/stdc++.h>
using namespace std;
int a[1005];
int muti[1005];
int N,K,P;
int ans = -1;
int ans_a[1005];

void dfs(int depth,int index,int sum,int factor_sum){
	if(depth==K && sum==N){
		if(factor_sum>ans){
			ans = factor_sum;
			for(int i=0;i<depth;i++){
				ans_a[i] = a[i];
			}
		}
		return;
	}
	
	if(sum>N || depth>K){
		return;
	}
	
	if(index>=1){
		a[depth] = index;
		dfs(depth+1,index,sum+muti[index],factor_sum+index);
		a[depth] = 0;
		dfs(depth+0,index-1,sum+0,factor_sum+0);
	}
		
}

int main(){
	cin >> N >> K >> P;
	
	int index_start;
	for(int i=0;;i++){
		int tmp = 1;
		for(int j=1;j<=P;j++){
			tmp = tmp * i;
		}
		if(tmp>N){
			index_start = i-1;
			break;
		}else{
			muti[i] = tmp;
		}
	}
	
	dfs(0,index_start,0,0);
	
	if(ans==-1){
		printf("Impossible\n");
	}else{
		printf("%d = ",N);
		for(int i=0;i<K;i++){
			printf("%d^%d",ans_a[i],P);
			if(i!=K-1){
				printf(" + ");
			}
		}
		printf("\n");
	}
	
	
	return 0;
} 

1104 Sum of Number Segments (20 分)

算法标签: 数论
注意点: 强制类型转换

#include<bits/stdc++.h>
using namespace std;

int main(){
	double a;
	int N;
	scanf("%d",&N);
	long long result = 0;
	for(int i=1;i<=N;i++){
		scanf("%lf",&a);
		result = result + ((long long)(1000.0*a))*(i) * (N-i+1);
	}
	double r = result*1.0/1000.0;
	printf("%.2lf",r);
	
	return 0;
}

1105 Spiral Matrix (25 分)

算法标签: 模拟
注意点: 模拟边界

#include<bits/stdc++.h>
using namespace std;
int N;
int m,n;
int b[10005];
int main(){
	cin >> N;
	for(int i=(ceil)(sqrt(N));i<=N;i++){
		if(N%i==0){
			m = i;
			n = N/i;
			break;
		}
	} 
	for(int i=0;i<N;i++){
		cin >> b[i];
	}
	sort(b,b+N);
	int a[m+1][n+1];
	memset(a,0,sizeof(a));
	int i = 0;
	int j = 0;
	while(N){
		while(j<n && !a[i][j]){
			a[i][j++] = b[--N];
		}
		j--;
		i++;
		while(i<m && !a[i][j]){
			a[i++][j] = b[--N];
		} 
		i--;
		j--;
		while(j>=0 && !a[i][j]){
			a[i][j--] = b[--N];
		}
		j++;
		i--;
		while(i>=0 && !a[i][j]){
			a[i--][j] = b[--N];
		}
		i++;
		j++;
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			if(j!=n-1){
				cout << a[i][j] << " ";
			}else{
				cout << a[i][j];
			}
		}
		cout << endl;
	}
	return 0;
}

1106 Lowest Price in Supply Chain (25 分)

算法标签: 树,二叉树 + DFS
注意点: 参考P1021/P1053/P1079/P1086/P1090/P1102,解法相同

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
vector<int> child[maxn];
int N;
double P;
double r;
bool hashT[maxn];
int mindepth = INT_MAX;
int minnum = 0;
void dfs(int depth,int root){
	if(child[root].size()==0){
		if(depth<mindepth){
			mindepth = depth;
			minnum = 1;
		}else if(depth==mindepth){
			minnum ++;
		}
		return;
	}
	for(int i=0;i<child[root].size();i++){
		dfs(depth+1,child[root][i]);
	}
}
int main(){
	cin >> N >> P >> r;
	for(int i=0;i<N;i++){
		int k;
		scanf("%d",&k);
		if(k==0){
			continue;
		}else{
			for(int j=0;j<k;j++){
				int t;
				scanf("%d",&t);
				child[i].push_back(t);
				hashT[t] = 1;
			}
		}
	}
	int root;
	for(int i=0;i<N;i++){
		if(!hashT[i]){
			root = i;
			break;
		}
	}
	dfs(0,root);
	printf("%.4lf %d\n",P*pow(1+r/100.0,mindepth),minnum);
	return 0;
}

1107 Social Clusters (30 分)

算法标签: 并查集
注意点: 路径压缩

#include<bits/stdc++.h>
using namespace std;
int father[1005];
int vis[1005];
int course[1005];

int findfather(int x){
	if(x == father[x]){
		return x;
	}else{
		int F = findfather(father[x]);
		father[x] = F;
		return F;
	}
}

void Union(int a,int b){
	int fa = findfather(a);
	int fb = findfather(b);
	if(fa!=fb){
		father[fa] = fb;
	}
}

vector<int> v;

int main(){
	int N;
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		father[i] = i;
	}
	for(int i=1;i<=N;i++){
		int k;
		scanf("%d:",&k);
		for(int j=0;j<k;j++){
			int t;
			scanf("%d",&t);
			if(!course[t]){
				course[t] = i;
			}
			Union(i,findfather(course[t]));
		}
	}
	for(int i=1;i<=N;i++){
		vis[findfather(i)]++;
	}

	for(int i=1;i<=N;i++){
		if(vis[i]){
			v.push_back(vis[i]);
		} 
	}
	sort(v.begin(),v.end());
	reverse(v.begin(),v.end());
	printf("%d\n",v.size());
	for(int i=0;i<v.size();i++){
		if(i==0){
			printf("%d",v[i]);
		}else{
			printf(" %d",v[i]); 
		}
	}
	printf("\n");
	return 0;
} 

1108 Finding Average (20 分)

算法标签: 模拟
注意点: 关于符合条件的数,需要筛选,然后按要求输出即可

#include<bits/stdc++.h>
using namespace std;
int main(){
	int N;
	cin.tie(0);
	cout.tie(0);
	cin >> N;
	int count = 0;
	double res = 0.0;
	for(int i=0;i<N;i++){
		char str1[100];
		scanf("%s",str1);
		double num = 0.0;
		sscanf(str1,"%lf",&num);
		char str2[100];
		sprintf(str2,"%.2lf",num);
		bool flag = false;
		for(int j=0;str1[j]!='\0';j++){
			if(str1[j]!=str2[j]){
				flag = true;
				break;
			}
		}
		if(flag || num<-1000 || num>1000){
			cout << "ERROR: "<< str1 << " is not a legal number" << endl;
		}else{
			count ++;
			res += num;
		}
	}
	
	if(count==1){
		printf("The average of 1 number is %.2lf\n",res);
	}else if(count==0){
		cout << "The average of 0 numbers is Undefined" << endl;
	}else{
		res = res / count;
		printf("The average of %d numbers is %.2lf\n",count,res);
	}
	return 0;
} 

1109 Group Photo (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
typedef struct photo{
	string name;
	int height;
}photo;
const int maxn = 1e4+5;
photo p[maxn];
int a[maxn];

int N,K;
bool cmp(photo p1,photo p2){
	if(p1.height>p2.height){
		return true;
	}else if(p1.height==p2.height){
		if(p1.name<p2.name){
			return true;
		}else{
			return false;
		}
	}else{
		return false;
	}
}
int main(){
	cin.tie(0);
	cout.tie(0);
	cin >> N >> K;
	int num = (int)(N/K);
	for(int i=0;i<N;i++){
		cin >> p[i].name >> p[i].height;
	}
	sort(p,p+N,cmp);
	
	int start = (N - num*K) + num;
	for(int i=0;i<start;i++){
		if(i%2==1){
			int site = (start/2)-((ceil)(i*1.0/2.0));
			a[site] = i;
		}else{
			int site = (start/2)+((ceil)(i*1.0/2.0));
			a[site] = i;
		}
	}
	
	for(int i=0;i<start;i++){
		if(i==0){
			cout << p[a[i]].name;
		}else{
			cout << " " << p[a[i]].name;
		}
	}
	cout << endl;

	for(int i=1;i<K;i++){
		for(int j=0;j<num;j++){
			if(j%2==1){
				int site = (num/2)-((ceil)(j*1.0/2.0));
				a[site] = (i-1)*num + start + j;
			}else{
				int site = (num/2)+((ceil)(j*1.0/2.0));
				a[site] = (i-1)*num + start + j;
			}
		}
		for(int j=0;j<num;j++){
			if(j==0){
				cout << p[a[j]].name;
			}else{
				cout << " " << p[a[j]].name;
			}
		}
		cout << endl;
	}
	return 0;
} 

1110 Complete Binary Tree (25 分)

算法标签: 树,二叉树 + BFS
注意点: 完全二叉树的定义,具体解法可参考P1021/P1053/P1079/P1086/P1090/P1102/P1106,解法相同

#include<bits/stdc++.h>
using namespace std;
int N;
struct node{
	int lchild = -1;
	int rchild = -1; 
};
node tree[105];
bool hashT[105];
int cnt = 0;

int LevelOrder(int root){
	queue<int> q;
	q.push(root);
	int last;
	while(!q.empty()){
		int f = q.front();
		q.pop();
		last = f;
		cnt++;
		if(cnt*2+1<=N){
			if(tree[f].lchild==-1 || tree[f].rchild==-1){
				return -1;
			}
		}else if(cnt*2<=N){
			if(tree[f].lchild==-1 || tree[f].rchild!=-1){
				return -1;
			}
		}else{
			if(tree[f].lchild!=-1 || tree[f].rchild!=-1){
				return -1;
			}
		}
		if(tree[f].lchild!=-1){
			q.push(tree[f].lchild);
		}
		if(tree[f].rchild!=-1){
			q.push(tree[f].rchild);
		}
	}
	if(cnt==N){
		return last;
	}else{
		return -1;
	}
}

int main(){
	cin >> N;
	for(int i=0;i<N;i++){
		string s;
		cin >> s;
		if(s[0]>='0' && s[0]<='9'){
			int t = 0;
			for(int i=0;i<s.size();i++){
				t =  t*10 +s[i]-'0';
			}
			tree[i].lchild = t;
			hashT[t] = 1;
		}else{
			tree[i].lchild = -1;
		}
		cin >> s;
		if(s[0]>='0' && s[0]<='9'){
			int t = 0;
			for(int i=0;i<s.size();i++){
				t =  t*10 +s[i]-'0';
			}
			tree[i].rchild = t;
			hashT[t] = 1;
		}else{
			tree[i].rchild = -1;
		}
	}
	int root;
	for(int i=0;i<N;i++){
		if(!hashT[i]){
			root = i;
			break;
		}
	}
	
	int f = LevelOrder(root);
	
	if(f!=-1){
		printf("YES %d\n",f);
	}else{
		printf("NO %d\n",root);
	}
	
	return 0;
}

1111 Online Map (30 分)

算法标签: 图论 + Dijkstra
注意点: 路径的记录和保存,参考P1003/P1018/P1030/P1072/P1087,解法相同

#include<bits/stdc++.h>
using namespace std;
struct node{
	int v;
	int length;
	int time;
};
node temp;
vector<node> G[505];
int N,M;
int S,T;

bool vis[505];
int vertex[505];
int dp[505];
int Time[505];
int path1[505];
int path2[505];

void dijstra1(int u){
	memset(vis,0,sizeof(vis));
	memset(dp,0x3f,sizeof(dp));
	memset(Time,0x3f,sizeof(Time));
	
	dp[u] = 0;
	Time[u] = 0;
	
	for(int i=0;i<N;i++){
		int u = -1;
		int minnum = INT_MAX;
		for(int j=0;j<N;j++){
			if(!vis[j] && dp[j]<minnum){
				minnum = dp[j];
				u = j;
			}
		}
		if(u==-1){
			return;
		}
		vis[u] = true;
		for(int j=0;j<G[u].size();j++){
			int v = G[u][j].v;
			int dis = G[u][j].length;
			int t = G[u][j].time;
			if(!vis[v]){
				if(dp[u]+dis<dp[v]){
					dp[v] = dp[u] + dis;
					Time[v] = Time[u] + t;
					path1[v] = u;
				}else if(dp[u]+dis==dp[v]){
					if(Time[u] + t < Time[v]){
						Time[v] = Time[u] + t;
						path1[v] = u;
					}
				}	
			}
		}
	}
}

void dijstra2(int u){
	memset(vis,0,sizeof(vis));
	memset(Time,0x3f,sizeof(Time));
	memset(vertex,0x3f,sizeof(vertex));
	
	Time[u] = 0;
	vertex[u] = 0;
	
	for(int i=0;i<N;i++){
		int u = -1;
		int minnum = INT_MAX;
		for(int j=0;j<N;j++){
			if(!vis[j] && Time[j]<minnum){
				minnum = Time[j];
				u = j;
			}
		}
		if(u==-1){
			return;
		}
		vis[u] = true;
		for(int j=0;j<G[u].size();j++){
			int v = G[u][j].v;
			int dis = G[u][j].length;
			int t = G[u][j].time;
			if(!vis[v]){
				if(Time[u]+t<Time[v]){
					Time[v] = Time[u] + t;
					vertex[v] = vertex[u] + 1;
					path2[v] = u;
				}else if(Time[u] + t == Time[v]){
					if(vertex[u]+1<vertex[v]){
						vertex[v] = vertex[u] + 1;
						path2[v] = u;
					}
				}	
			}
		}
	}
}

vector<int> ans1;
vector<int> ans2;

void dfs1(int T){
	if(T==S){
		ans1.push_back(T);
		return;
	}
	dfs1(path1[T]);
	ans1.push_back(T); 
}
void dfs2(int T){
	if(T==S){
		ans2.push_back(T);
		return;
	}
	dfs2(path2[T]);
	ans2.push_back(T); 
}

int main(){
	scanf("%d%d",&N,&M);
	for(int i=0;i<M;i++){
		int u,v;
		int q;
		int length,time;
		scanf("%d%d%d%d%d",&u,&v,&q,&length,&time);
		if(q==1){
			temp.v = v;
			temp.length = length;
			temp.time = time;
			G[u].push_back(temp); 
		}else{
			temp.v = v;
			temp.length = length;
			temp.time = time;
			G[u].push_back(temp); 
			temp.v = u;
			G[v].push_back(temp);
		}
	}
	scanf("%d%d",&S,&T);
	
	dijstra1(S);
	dfs1(T);
	dijstra2(S);
	dfs2(T);
	
	if(ans1==ans2){
		printf("Distance = %d; ",dp[T]);
		printf("Time = %d: ",Time[T]);	
		for(int i=0;i<ans1.size();i++){
			if(i==0){
				printf("%d",ans1[i]); 
			}else{
				printf(" -> %d",ans1[i]);
			}
		}
		printf("\n");
	}else{
		printf("Distance = %d: ",dp[T]);
		for(int i=0;i<ans1.size();i++){
			if(i==0){
				printf("%d",ans1[i]); 
			}else{
				printf(" -> %d",ans1[i]);
			}
		}
		printf("\n");
		printf("Time = %d: ",Time[T]);	
		for(int i=0;i<ans2.size();i++){
			if(i==0){
				printf("%d",ans2[i]); 
			}else{
				printf(" -> %d",ans2[i]);
			}
		}
		printf("\n");
	}
	
	
	return 0;
} 

1112 Stucked Keyboard (20 分)

算法标签: 字符串 + 模拟

#include<bits/stdc++.h>
using namespace std;
string s = "abcdefghijklmnopqrstuvwxyz0123456789_";
bool hashT[40];
string s1 = "";

int main(){
	int n;
	cin >> n;
	string in;
	cin >> in;
	string out = "";
	for(int i=0;i<in.size();i++){
		if(in[i]>='a' && in[i]<='z'){
			if(!hashT[in[i]-'a']){
				hashT[in[i]-'a'] = 1;
				s1 += in[i];
			}
		}else if(in[i]>='0' && in[i]<='9'){
			if(!hashT[in[i]-'0'+26]){
				hashT[in[i]-'0'+26] = 1;
				s1 += in[i];
			}
		}else{
			if(!hashT[36]){
				hashT[36] = 1;
				s1 += in[i];
			}
		}
	}
	
	for(int i=0;i<s1.size();i++){
		string t = "";
		for(int j=0;j<n;j++){
			t += s1[i];
		}
		string tmp = in;
		int x = tmp.find(t);
		int cnt = 0;
		while(x!=-1){
			cnt++;
			tmp = tmp.substr(0,x) + s1[i] + tmp.substr(x+n);
			x = tmp.find(t,x+1);
		}
		int res = 0;
		for(int j=0;j<tmp.size();j++){
			if(tmp[j]==s1[i]){
				res++;
			}
		}
		if(res == cnt && cnt){
			in = tmp;
			out += s1[i];
		}
	}
	cout << out << endl;
	cout << in << endl;
	return 0;
} 

1113 Integer Set Partition (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];

int main(){
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		scanf("%d",&a[i]);
	}
	sort(a,a+N);
	long long ans = 0;
	long long res;
	if(N%2){
		res = 1;
	}else{
		res = 0;
	}
	for(int i=0;i<N/2;i++){
		ans -= a[i];
	}
	for(int i=N/2;i<N;i++){
		ans += a[i];
	}
	printf("%lld %lld\n",res,ans);
	return 0;
}
 

1114 Family Property (25 分)

算法标签: 并查集 + 排序
注意点: 本题极易与树、二叉树知识点混淆,该题的正确解法是并查集操作,合并parent与child,然后划定area

#include<bits/stdc++.h>
using namespace std;
struct person{
	int father;
	int mother;
	vector<int> child;
	int Mstate;
	int Area;
	bool f = false;
};
person p[10005];

int father[10005];

int findfather(int x){
	if(x == father[x]){
		return x;
	}else{
		int F = findfather(father[x]);
		father[x] = F;
		return F;	
	}
}

void Union(int a,int b){
	int fa = findfather(a);
	int fb = findfather(b);
	if(fa!=fb){
		if(fa<fb){
			father[fb] = fa;
		}else{
			father[fa] = fb;	
		}
	}
}

int num[10005];
double area[10005];
double state[10005];


struct ans{
	int ID;
	int number;
	double state;
	double area;
};
ans a[10005];

bool vis[10005];
bool hashT[10005];

int cnt = 0;

bool cmp(ans a1,ans a2){
	if(a1.area!=a2.area){
		return a1.area > a2.area;
	}else{
		return a1.ID < a2.ID;	
	}
}

int main(){
	for(int i=0;i<=9999;i++){
		father[i] = i;
	}
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		int id;
		scanf("%d",&id);
		hashT[id] = true;
		scanf("%d%d",&p[id].father,&p[id].mother);
		if(p[id].father!=-1){
			hashT[p[id].father] = true;
			Union(id,p[id].father);
		}
		if(p[id].mother!=-1){
			hashT[p[id].mother] = true;
			Union(id,p[id].mother);
		}
		int k;
		scanf("%d",&k);
		for(int j=0;j<k;j++){
			int cid;
			scanf("%d",&cid);
			p[id].child.push_back(cid);
			hashT[cid] = true;
			Union(id,cid);
		}
		scanf("%d%d",&p[id].Mstate,&p[id].Area);
		p[id].f = true;
	}
	
	
	for(int i=0;i<=9999;i++){
		int F = findfather(i);
		num[F]++;
		if(p[i].f){
			area[F] += p[i].Area;
			state[F] += p[i].Mstate;
		}
	}
	
	for(int i=0;i<=9999;i++){
		if(hashT[i]){
			int F = findfather(i);
			if(!vis[F] && num[F]){
				vis[F] = true;
				a[cnt].ID = i;
				a[cnt].number = num[F];
				a[cnt].state = state[F]/(num[F]*1.0);
				a[cnt].area = area[F]/(num[F]*1.0);
				cnt++;
			}	
		}
	}
	
	sort(a,a+cnt,cmp);
	printf("%d\n",cnt);
	for(int i=0;i<cnt;i++){
		printf("%04d %d %.3lf %.3lf\n",a[i].ID,a[i].number,a[i].state,a[i].area);
	}
	
	return 0;
} 

1115 Counting Nodes in a BST (30 分)

算法标签: 树,二叉树 + DFS
注意点: 树 基础题,可参考P1021/P1053/P1079/P1086/P1090/P1102/P1106/P1110,解法相同

#include<bits/stdc++.h>
using namespace std;
struct node{
	int data;
	node *lchild;
	node *rchild;
};
node* root = NULL;
node* newnode(int v){
	node* Node = new node;
	Node->data = v;
	Node->lchild = NULL;
	Node->rchild = NULL;
	return Node;
}
void insert(node* &root,int x){
	if(root==NULL){
		root = newnode(x);
		return;
	}
	if(x<=root->data){
		insert(root->lchild,x); 
	}else{
		insert(root->rchild,x);
	}
}
int a[1005];
int maxdepth = -1;
void dfs(node* root,int depth){
	if(root==NULL){
		return;
	}
	a[depth]++;
	maxdepth = max(maxdepth,depth);
	if(root->lchild){
		dfs(root->lchild,depth+1);
	}
	if(root->rchild){
		dfs(root->rchild,depth+1);
	}
}
int main(){
	int N;
	cin >> N;
	for(int i=0;i<N;i++){
		int t;
		cin >> t;
		insert(root,t);
	}
	dfs(root,0);
	int n1,n2;
	n1 = a[maxdepth];
	n2 = a[maxdepth-1];
	printf("%d + %d = %d\n",n1,n2,n1+n2);
	return 0;
}

1116 Come on! Let’s C (20 分)

算法标签: 素数 + 模拟

#include<bits/stdc++.h>
using namespace std;
int N,K;
const int maxn = 1e4+5;
typedef struct competition{
	int ID;
	int rank;
	bool check;
	bool isin;
}competition;
competition c[maxn];
int isprime(int num){
	if(num<2){
		return 0;
	}else{
		for(int i=2;i<=sqrt(num);i++){
			if(num%i==0){
				return 0;
			}
		}
		return 1;
	}
}
int main(){
	cin >> N;
	for(int i=0;i<N;i++){
		int id;
		cin >> id;
		c[id].ID = id;
		c[id].rank = i+1;
		c[id].check = false;
		c[id].isin = true;
	}
	cin >> K;
	for(int i=0;i<K;i++){
		int id;
		cin >> id;
		int g,s,b,q;
		g = id % 10;
		s = id/10 %10;
		b = id/100 %10;
		q = id /1000;
		cout << q << b << s << g;
		if(c[id].isin==true){
			if(c[id].check==true){
				cout << ": Checked"<< endl;
			}else{
				if(c[id].rank==1){
					cout << ": Mystery Award"<<endl;
					c[id].check=true;
				}else if(isprime(c[id].rank)){
					cout << ": Minion" << endl;
					c[id].check=true;
				}else{
					cout << ": Chocolate" << endl;
					c[id].check=true;
				}
			}
		}else{
			cout << ": Are you kidding?" << endl;
		}
	}
	return 0;
}

1117 Eddington Number (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
int N;
const int maxn = 1e5+5;
int a[maxn];
int E;
bool cmp(int a,int b){
	return a>b;
}
int main(){
	cin >> N;
	cin.tie(0);
	cout.tie(0);
	for(int i=1;i<=N;i++){
		cin >> a[i];
	}	
	sort(a+1,a+N+1,cmp);
	for(int i=1;i<=N;i++){
		if(a[i]>i){
			E = i;
		}else{
			break;
		}
	}
	cout << E << endl;
	return 0;
}

1118 Birds in Forest (25 分)

算法标签: 并查集
注意点: 路径压缩

#include<bits/stdc++.h>
using namespace std;
int N,Q;
int father[10005];
bool bird[10005];

int findfather(int x){
	if(x == father[x]){
		return x;
	}else{
		int F = findfather(father[x]);
		father[x] = F;
		return F;
	}
}

void Union(int a,int b){
	int fa = findfather(a);
	int fb = findfather(b);
	if(fa!=fb){
		father[fa] = fb;
	}
}

int main(){
	for(int i=0;i<=10000;i++){
		father[i] = i;
	}
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		int K;
		scanf("%d",&K);
		int top;
		scanf("%d",&top);
		bird[top] = true;
		
		for(int j=1;j<K;j++){
			int t;
			scanf("%d",&t);
			bird[t] = true;
			Union(top,t);
		}
	}	
	int cnt = 0;
	set<int> s;
	for(int i=1;i<=10000;i++){
		if(bird[i]){
			s.insert(findfather(i));
			cnt++;
		}
	}
	printf("%d %d\n",s.size(),cnt);
	scanf("%d",&Q);
	for(int i=0;i<Q;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		int fa = findfather(u);
		int fb = findfather(v);
		if(fa == fb){
			printf("Yes\n");
		}else{
			printf("No\n");
		}
	}
	return 0;
} 

1119 Pre- and Post-order Traversals (30 分)

算法标签: 树,二叉树
注意点: 整体的思路和普通二叉树建树的方法一样,先定根结点,我们从后序遍历倒着找根,然后再从前序遍历中找这个结点,若前序遍历的第一个结点和后序遍历的最后一个结点相同,意味着这个就是根结点,可建立该结点,然后从后序遍历中找右子树的根结点,根据该结点,将前序遍历分成2部分,左半部分对应着左子树,右半部分对应着右子树,可递归建树,但是这里还存在一种情况,就是左子树为空的时候,此时只有一棵子树,那么这个结点既可以当成左子树,也可以当作右子树,也就是所说的不唯一,此时,我们不妨将该结点并入右子树之中,而左子树设置为空

#include<bits/stdc++.h>
using namespace std;
int N;
int pre[35];
int post[35];

struct node{
 	int data;
	node* lchild;
	node* rchild;
};
node* newnode(int v){
	node* Node = new node;
	Node->data = v;
	Node->lchild = NULL;
	Node->rchild = NULL;
	return Node;
}
int cnt = 0;
int a[35];
void inorder(node* root){
	if(root==NULL){
		return;
	}
	inorder(root->lchild);
	a[cnt++] = root->data;
	inorder(root->rchild);
}
bool f = true;
node* Create(int preL,int preR,int postL,int postR){
	if(preL == preR){
		return newnode(pre[preL]);
	}
	if(pre[preL] == post[postR]){
		node* root = newnode(pre[preL]);
		int k;
		for(int i=preL+1;i<=preR;i++){
			if(pre[i] == post[postR-1]){
				k = i;
				break;
			}
		}	
		int numleft = k-preL;
		if(k-preL>1){
			root->lchild = Create(preL+1,preL+numleft-1,postL,postL+numleft-2);
		}else{
			f = false;
		}
		
		root->rchild = Create(preL+numleft,preR,postL+numleft-1,postR-1);
		return root;
	}
}

int main(){
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%d",&pre[i]);
	}
	for(int i=1;i<=N;i++){
		scanf("%d",&post[i]);
	}
	node *root = Create(1,N,1,N);
	if(f){
		printf("Yes\n");
	}else{
		printf("No\n");
	}
	inorder(root);
	for(int i=0;i<cnt;i++){
		if(i==0){
			printf("%d",a[i]);
		}else{
			printf(" %d",a[i]);
		}
	}
	printf("\n");
	return 0;
} 

1120 Friend Numbers (20 分)

算法标签: 模拟

#include<bits/stdc++.h>
using namespace std;
int N;
int a[40];

int main(){
	cin.tie(0);
	cout.tie(0);
	cin >> N;
	for(int i=0;i<N;i++){
		int s;
		int result = 0;
		cin >> s;
		while(s>0){
			result += s%10;
			s /= 10;
		}
		a[result] = 1;
	}
	
	int count = 0;
	for(int i=0;i<40;i++){
		if(a[i]){
			count++;
		}
	}
	cout << count << endl;
	count = 0;
	for(int i=0;i<40;i++){
		if(a[i]){
			if(count==0){
				cout << i;
			}else{
				cout << " " << i;
			}
			count++;
		}
	}
	return 0;
} 

1121 Damn Single (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
int N,M;
const int maxn = 1e5+5;
int a[maxn];
int out[maxn];
int pairs[maxn];
typedef struct man{
	int pair1;
	int pair2;
	bool flag1;
	bool flag2;
}man;
man m[maxn];

int main(){
	cin.tie(0);
	cout.tie(0);
	cin >> N;
	for(int i=0;i<N;i++){
		int p,q;
		cin >> p >> q;
		a[p] = 1;
		a[q] = 1;
		m[i+1].pair1 = p;
		m[i+1].pair2 = q;
		m[i+1].flag1 = false;
		m[i+1].flag2 = false;
		pairs[p] = i+1;
		pairs[q] = i+1;
	}
	
	cin >> M; 
	int count = 0;
	for(int i=0;i<M;i++){
		int n;
		cin >> n;
		if(!a[n]){
			out[count++] = n;
		}else{
			int pairnum = pairs[n];
			if(n==m[pairnum].pair1){
				m[pairnum].flag1 = true;
			}else if(n==m[pairnum].pair2){
				m[pairnum].flag2 = true;
			}
		}
	} 
	for(int i=1;i<=N;i++){
		if(m[i].flag1 == false && m[i].flag2 == true){
			out[count++] = m[i].pair2;
		}else if(m[i].flag1 == true && m[i].flag2 == false){
			out[count++] = m[i].pair1;
		}
	}
	sort(out,out+count);
	cout << count << endl;
	for(int i=0;i<count;i++){
		int w,q,b,s,g;
		w = out[i] / 10000;
		q = out[i] / 1000 % 10;
		b = out[i] / 100 % 10;
		s = out[i] / 10 % 10;
		g = out[i] % 10;
		if(i==0){
			cout << w << q << b << s << g;
		}else{
			cout << " " << w << q << b << s << g;
		}
	}
	return 0;
} 

1122 Hamiltonian Cycle (25 分)

算法标签: 图论 汉密尔顿环路
注意点: 所有顶点均访问一遍后即为汉密尔顿环路

#include<bits/stdc++.h>
using namespace std;

vector<int> G[205];
int N,M,K; 
int a[1005];
bool vis[205];

int main(){
	scanf("%d%d",&N,&M);
	for(int i=1;i<=M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	scanf("%d",&K);
	for(int i=1;i<=K;i++){
		memset(vis,0,sizeof(vis));
		int n;
		scanf("%d",&n);
		for(int j=1;j<=n;j++){
			scanf("%d",&a[j]);
		}
		if(n!=N+1){
			printf("NO\n");
		}else{
			if(a[1] == a[n]){
				bool f = false;
				for(int j=1;j<=N;j++){
					if(!vis[a[j]]){
						vis[a[j]] = true;
					}else{
						f = true;
						break;
					}
				}
				for(int j=1;j<=N;j++){
					int u = a[j];
					int v = a[j+1];
					bool f1 = true;
					for(int k=0;k<G[u].size();k++){
						int v1 = G[u][k];
						if(v1 == v){
							f1 = false;
							break;
						}
					}
					if(f1){
						f = true;
						break;
					}
				}
				if(!f){
					printf("YES\n");
				}else{
					printf("NO\n");	
				}
			}else{
				printf("NO\n");	
			}
		}
	}
	return 0;
} 

1123 Is It a Complete AVL Tree (30 分)

算法标签: 树,二叉树 + BFS
注意点: 先按照平衡树插入每个结点,然后再判断完全二叉树是否满足,此外,可参考P1021/P1053/P1079/P1086/P1090/P1102/P1106/P1110/P1115,解法相同

#include<bits/stdc++.h>
using namespace std;
int a[25];

struct node{
	int data;
	node* lchild;
	node* rchild;
	int height;
};

node* newnode(int v){
	node* Node = new node;
	Node->data = v;
	Node->lchild = NULL;
	Node->rchild = NULL;
	Node->height = 1;
	return Node;
}

int getheight(node* root){
	if(root==NULL){
		return 0;
	}
	return root->height;
}
int bf(node* root){
	return getheight(root->lchild) - getheight(root->rchild);
}
void updateheight(node* root){
	root->height = max(getheight(root->lchild),getheight(root->rchild)) + 1;
}

void L(node* &root){
	node* temp = root->rchild;
	root->rchild = temp->lchild;
	temp->lchild = root;
	updateheight(root);
	updateheight(temp);
	root = temp;
}

void R(node* &root){
	node* temp = root->lchild;
	root->lchild = temp->rchild;
	temp->rchild = root;
	updateheight(root);
	updateheight(temp);
	root = temp;
}

void insert(node* &root,int v){
	if(root == NULL){
		root = newnode(v);
		return;
	}
	if(v<root->data){
		insert(root->lchild,v);
		updateheight(root);
		if(bf(root) == 2){
			if(bf(root->lchild)==1){
				R(root);
			}else if(bf(root->lchild)==-1){
				L(root->lchild);
				R(root);
			}
		}
	}else{
		insert(root->rchild,v);
		updateheight(root);
		if(bf(root)==-2){
			if(bf(root->rchild)==-1){
				L(root);
			}else if(bf(root->rchild)==1){
				R(root->rchild);
				L(root);
			}
		} 
	}
}

int flag = 1;
bool isCBT = true;
void LevelOrder(node* root){
	queue<node*> q;
	q.push(root);
	int cnt = 0;
	while(!q.empty()){
		node* f = q.front();
		q.pop();
		if(cnt==0){
			printf("%d",f->data);
		}else{
			printf(" %d",f->data);
		}
		cnt++;
		if(f->lchild){
			if(flag == -1){
				isCBT = false;
			}
			q.push(f->lchild);
		}else{
			flag = -1;
		}
		if(f->rchild){
			if(flag == -1){
				isCBT = false;
			}
			q.push(f->rchild); 
		}else{
			flag = -1;
		}
	}
	printf("\n");
}
int main(){
	int N;
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%d",&a[i]); 
	} 
	node* root = NULL;
	for(int i=1;i<=N;i++){
		insert(root,a[i]);
	}
	LevelOrder(root);
	if(isCBT){
		printf("YES\n"); 
	}else{
		printf("NO\n");
	}
	return 0;
} 

1124 Raffle for Weibo Followers (20 分)

算法标签: 模拟

#include<bits/stdc++.h>
using namespace std;
int M,N,S;
const int maxn = 1e3+5;
string award[maxn];

int main(){
	cin >> M >> N >> S;
	string str;
	int count = 1;
	int num = 0;
	for(int i=0;i<M;i++){
		cin >> str;
		if((count-S)%N==0 && count>=S){
			bool flag = false;
			for(int i=0;i<num;i++){
				if(award[i]==str){
					flag = true;
					break;
				}
			}
			if(flag==true){
				continue;
			}else if(flag==false){
				cout << str << endl;
				award[num++] = str;
				count++;
			}
		}else{
			count++;
		}
	}
	if(num==0){
		cout << "Keep going..." << endl;
	}
	return 0;
}

1125 Chain the Ropes (25 分

算法标签: 模拟 + 排序

#include<bits/stdc++.h>
using namespace std;
int N;
const int maxn = 1e5+5;
int a[maxn];
int main(){
	cin.tie(0);
	cout.tie(0);
	cin >> N;
	for(int i=0;i<N;i++){
		cin >> a[i];
	}
	sort(a,a+N);
	double res = (a[0]+a[1])*1.0/2.0;
	for(int i=2;i<N;i++){
		res = (res +a[i])/2.0;
	}
	int result = (floor)(res);
	cout << result << endl;
	return 0;
} 

1126 Eulerian Path (25 分)

算法标签: 图论 + 欧拉回路
注意点:
1.欧拉路径的定义:全是偶数度结点且图连通为欧拉路径,若存在2个奇数度结点且其余都是偶数度结点,且起点和终点分别为奇数度结点的连通图,称为半欧拉路径,若以上都不是,那么不是欧拉路径
2.此题有几个容易错误的点:
首先判断图是否连通,不连通,那么一定不是欧拉图
其次,注意起点和终点,欧拉回路要求起点和终点相同;半欧拉回路要求分别是两个不同的奇数度顶点
3.题目中未对简单路径和复杂路径作区分,因此存在重边也是合理的

#include<bits/stdc++.h>
using namespace std;
int N,M;
int degree[505];

vector<int> G[505];
int odd = 0,even = 0;
bool vis[505];
int cnt = 0;
void bfs(int s){
	queue<int> q;
	vis[s] = true;
    q.push(s);
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int i=0;i<G[u].size();i++){
			int v = G[u][i];
			if(!vis[v]){
				vis[v] = true;
				q.push(v);
			}
		}	
	}
}
int main(){
	scanf("%d%d",&N,&M);
	for(int i=0;i<M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u); 
		degree[u]++;
		degree[v]++;
	}
	for(int i=1;i<=N;i++){
		if(degree[i]%2){
			odd++;
		}else{
			even++;
		}
		if(i==1){
			printf("%d",degree[i]);
		}else{
			printf(" %d",degree[i]);
		}
	}
	printf("\n");
	for(int i=1;i<=N;i++){
		if(!vis[i]){
			bfs(i);
			cnt++;	
		}
	}
	if(odd == 0 && cnt==1){
		printf("Eulerian\n");
	}else if(odd == 2 && cnt==1){
		printf("Semi-Eulerian\n");
	}else{
		printf("Non-Eulerian\n");
	}
	return 0;
} 

1127 ZigZagging on a Tree (30 分)

算法标签: 树,二叉平衡树 + 排序
注意点:
1.首先根据后序和中序建树,此方法比较常规。
2.然后进行层序遍历,不同层的结点存储方式相反(zig-zag在本题目中的含义),输出结果即可

#include<bits/stdc++.h>
using namespace std;

int N;
int in[35];
int post[35];
int levelmax = 0;
vector<int> output[35];

struct node{
	int data;
	node* lchild;
	node* rchild;
	int level = 0;
};

node* newnode(int v){
	node* Node = new node;
	Node->data = v;
	Node->lchild = NULL;
	Node->rchild = NULL;
	return Node;
}
node* Create(int inL,int inR,int postL,int postR){
	if(inL>inR){
		return NULL;
	}
	node* root = newnode(post[postR]);
	int k;
	for(int i=inL;i<=inR;i++){
		if(in[i] == post[postR]){
			k = i;
			break;
		}
	}
	int numleft = k-inL;
	
	root->lchild = Create(inL,inL+numleft-1,postL,postL+numleft-1);
	root->rchild = Create(inL+numleft+1,inR,postL+numleft,postR-1);
	
	return root;
}

void levelorder(node* root){
	queue<node*> q;
	q.push(root);
	root->level = 0;
	while(!q.empty()){
		node* f = q.front();
		q.pop();
		output[f->level].push_back(f->data);
		levelmax = max(levelmax,f->level);
		if(f->lchild){
			f->lchild->level = f->level + 1;
			q.push(f->lchild);
		}
		if(f->rchild){
			f->rchild->level = f->level + 1;
			q.push(f->rchild);
		}
	}
}

int main(){
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%d",&in[i]);
	}	
	for(int i=1;i<=N;i++){
		scanf("%d",&post[i]);
	}
	node* root = Create(1,N,1,N);
	levelorder(root);
	for(int i=0;i<=levelmax;i++){
		if(i%2==0){
			reverse(output[i].begin(),output[i].end());
		}
	}
	int cnt = 0;
	for(int i=0;i<=levelmax;i++){
		for(int j=0;j<output[i].size();j++){
			if(cnt == 0){
				printf("%d",output[i][j]);
			}else{
				printf(" %d",output[i][j]);
			}
			cnt++;
		}
	}
	printf("\n");
	return 0;
}

1128 N Queens Puzzle (20 分)

算法标签: 模拟
注意点:
N皇后的判定问题
4个方向上均需要判断,同一行row,同一列column,主对角线,副对角线

#include<bits/stdc++.h>
using namespace std;
int a[1005];
int check(int row1,int column1,int row2,int column2){
	if(row1 == row2){
		return 0;
	}
	if(column1-row1 == column2-row2){
		return 0;
	}
	if(column1+row1 == column2+row2){
		return 0;
	}
	return 1;
}
int main(){
	int K;
	scanf("%d",&K);
	for(int i=1;i<=K;i++){
		memset(a,0,sizeof(a));
		int N;
		scanf("%d",&N);
		for(int i=1;i<=N;i++){
			scanf("%d",&a[i]);
		}
		int f;
		for(int i=1;i<=N-1;i++){
			f = 1;
			for(int j=i+1;j<=N;j++){
				f = check(a[i],i,a[j],j);
				if(f == 0){
					break;
				}
			}
			if(f == 0){
				break;
			}
		}
		if(f){
			printf("YES\n");
		}else{
			printf("NO\n");
		}	
	}
	
	return 0;
}

1129 Recommendation System (25 分)

算法标签: 模拟 + 排序
注意点:
模拟推荐系统的实现,一道好题!
考察了集合与结构体的复合结构,由于集合本身是红黑树的实现方式,因此定义的时候必须给出元素的优先级次序,然后根据访问的次数高低、key值进行排序,最后输出每时刻的结果

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
int a[maxn];
int hashT[maxn];

struct node{
	int key;
	int value;
	bool operator < (const node &a) const{
		if(a.value!= value){
			return value > a.value;
		}else{
			return key < a.key;
		}
	}
};

set<node> s;


int main(){
	int N,K;
	scanf("%d%d",&N,&K);
	for(int i=1;i<=N;i++){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=N;i++){
		if(i>1){
			printf("%d:",a[i]);
			int cnt = 0;
			auto it = s.begin();
			while(cnt<K && cnt<s.size()){
				printf(" %d",it->key);
				it++;
				cnt++;
			}
			printf("\n");
		}
		node temp;
		temp.key = a[i];
		temp.value = hashT[a[i]];
		auto it = s.find(temp);
		if(it!=s.end()){
			s.erase(it);
		}
		hashT[a[i]]++;
		temp.value = hashT[a[i]];
		s.insert(temp);
	}
	
	
	return 0;
}

1130 Infix Expression (25 分)

算法标签: 树,二叉树 + DFS
注意点:
中缀表达式本质上还是中序遍历,因此建树+中序遍历即可,注意进入子树需要加括号,以表示优先级的关系!

#include<bits/stdc++.h>
using namespace std;

int N;
int root;
struct node{
	string s;
	int lchild;
	int rchild;
};

node tree[25];
bool hashT[25];

stack<char> s;

void InOrder(int u){
	if(u == -1){
		return;
	}
	if(u!=root && (tree[u].lchild!=-1 || tree[u].rchild!=-1)){
		cout << "(";
	}
	InOrder(tree[u].lchild);
	cout << tree[u].s; 
	InOrder(tree[u].rchild);
	if(u!=root && (tree[u].lchild!=-1 || tree[u].rchild!=-1)){
		cout << ")";
	}
}
int main(){
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		cin >> tree[i].s >> tree[i].lchild >> tree[i].rchild;
	}
	for(int i=1;i<=N;i++){
		if(tree[i].lchild!=-1){
			hashT[tree[i].lchild] = true;
		}	
		if(tree[i].rchild!=-1){
			hashT[tree[i].rchild] = true;
		}
	}
	for(int i=1;i<=N;i++){
		if(!hashT[i]){
			root = i;
			break;
		}
	}
	InOrder(root);
	return 0;
} 

1131 Subway Map (30 分)

算法标签: 图论 + Dijkstra + DFS
注意点:
一道好题!实质上仍然是Dijkstra+DFS的模板题,可参考P1003/P1018/P1030/P1072/P1087/P1111
首先是求最短路,这个用Dijkstra算法肯定没问题,本题的关键在于如何找出一条路径满足换乘次数最少,且能输出换乘地铁的方式:
我们先解决后半个问题,如何输出地铁换乘的方式呢?由于每两个地铁站之间唯一确定一条地铁线路,因此只需建立一个 ( s t a t i o n 1 , s t a t i o n 2 ) = l i n e (station1,station2) = line (station1,station2)=line的关系映射就可以了,这里我们采用哈希表建立,记录每站的地铁选择,相同线路只输出一次,到了换乘站再输出下一行(路径压缩)
接着我们解决前半个问题,如何使得换乘次数最少?此时,我们需统计所有的最短路径(DFS),找出一条换乘次数最少的即可,保存并输出

#include<bits/stdc++.h>
using namespace std;
int a[105][105];
int b[105];

struct node{
	int v;
};
node temp;

vector<node> G[10005]; 
int dp[10005];
bool vis[10005];
map<int,int> mp;
int S,T;
vector<int> ans;
vector<int> res;
vector<int> pre[10005];
int maxn = 105;

void dijkstra(int u){
	memset(vis,0,sizeof(vis));
	memset(dp,0x3f,sizeof(dp));
	maxn = 105;
	for(int i=0;i<10000;i++){
		pre[i].clear();
	}
	dp[u] = 0;
	priority_queue<pair<int,int> > q;
	q.push(make_pair(-dp[u],u));
	while(!q.empty()){
		pair<int,int> f = q.top();
		q.pop();
		int u = f.second;
		if(vis[u]){
			continue;
		}
		vis[u] = true;
		for(int i=0;i<G[u].size();i++){
			int v = G[u][i].v;
			if(!vis[v]){
				if(dp[u] + 1 < dp[v]){			
					dp[v] = dp[u] + 1;
					pre[v].clear();
					pre[v].push_back(u);
					q.push(make_pair(-dp[v],v));
				}else if(dp[u] + 1 == dp[v]){	 
					pre[v].push_back(u);
				}	
			}
		}
	}
}

void dfs(int T){
	if(T == S){
		set<int> s;
		res.push_back(T);
		for(int i=0;i<res.size()-1;i++){
			int u = res[i];
			int v = res[i+1];
			int t = u*10000 + v;
			s.insert(mp[t]);
		}
		if(s.size()<maxn){
			maxn = s.size();
			ans = res;
		}
		res.pop_back();
		return;
	}

	for(int i=0;i<pre[T].size();i++){
		int v = pre[T][i];
		res.push_back(T); 
		dfs(v);
		res.pop_back();
	}
	
}

int main(){
	int N;
	cin >> N;
	for(int i=1;i<=N;i++){	
		cin >> b[i];
		for(int j=1;j<=b[i];j++){
			cin >> a[i][j];
		}
	}
	for(int i=1;i<=N;i++){
		for(int j=1;j<b[i];j++){
			int u = a[i][j];
			temp.v = a[i][j+1];
			int t = a[i][j]*10000 + a[i][j+1];
			mp[t] = i;
			G[u].push_back(temp);
			
			u = a[i][j+1];
			temp.v = a[i][j];
			t = a[i][j+1]*10000 + a[i][j];
			mp[t] = i;
			G[u].push_back(temp);
		}
	}
	int K;
	cin >> K;
	for(int i=1;i<=K;i++){
		cin >> S >> T;
		dijkstra(S);
		printf("%d\n",dp[T]);
		ans.clear();
		res.clear();
		dfs(T);
		reverse(ans.begin(),ans.end());
		int t = ans[0]*10000 + ans[1];
		int f = mp[t];
		int start = ans[0];
		for(int i=0;i<ans.size()-1;i++){
			t = ans[i]*10000 + ans[i+1];
			if(mp[t] == f){
				continue;
			}else{
				printf("Take Line#%d from %04d to %04d.\n",f,start,ans[i]);
				f = mp[t];
				start = ans[i];
			}
		}
		printf("Take Line#%d from %04d to %04d.\n",f,start,T);
	}
	return 0;
} 

1132 Cut Integer (20 分)

算法标签: 模拟

#include<bits/stdc++.h>
using namespace std;
int count(int n){
	int cnt = 0;
	while(n){
		cnt++;
		n/=10;
	}
	return cnt;
}

int main(){
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		int t;
		scanf("%d",&t);
		int cnt = count(t);
		cnt/=2;
		int mod = (int)pow(10,cnt);
		int num1 = t/mod;
		int num2 = t%mod;
		if(num2 == 0){
			printf("No\n");
		}else{
			int q = (t)/(num1*num2);
			if(q*num1*num2 == t){
				printf("Yes\n");
			}else{
				printf("No\n");
			}	
		}
	}
	
	return 0;
} 

1133 Splitting A Linked List (25 分)

算法标签: 链表 + 模拟

#include<bits/stdc++.h>
using namespace std;
map<int,int>mp1;
map<int,int> mp2;
struct node{
	int s1;
	int val;
};
node n[100005];

int main(){
	int N,K;
	int start;
	cin >> start >> N >> K;
	for(int i=0;i<N;i++){
		int pos,next;
		int v;
		cin >> pos >> v >>next;
		mp1[pos] = next;
		mp2[pos] = v;
	}
	int cnt = 0;
	int start1 = start;
	while(start1!=-1){
		if(mp2[start1]<0){
			n[cnt].s1 = start1;
			n[cnt++].val = mp2[start1];
		}
		start1 = mp1[start1];
	}
	start1 = start;
	while(start1!=-1){
		if(mp2[start1]>=0 && mp2[start1]<=K){
			n[cnt].s1 = start1;
			n[cnt++].val = mp2[start1];
		}
		start1 = mp1[start1];
	}
	start1 = start;
	while(start1!=-1){
		if(mp2[start1]>K){
			n[cnt].s1 = start1;
			n[cnt++].val = mp2[start1];
		}
		start1 = mp1[start1];
	}
	
	for(int i=0;i<cnt;i++){
		if(i==cnt-1){
			printf("%05d %d %d\n",n[i].s1,n[i].val,-1);
		}else{
			printf("%05d %d %05d\n",n[i].s1,n[i].val,n[i+1].s1);
		}
	}
	return 0;
}

1134 Vertex Cover (25 分)

算法标签: 顶点覆盖
注意点:
根据题意,顶点覆盖是指有这么一个点集,从点集中的点出发能够访问(覆盖)图中所有的边,也就是说点覆盖边,因此根据定义,直接判断边是否被完全标记即可

#include<bits/stdc++.h>
using namespace std;
int N,M;
int K;
struct node{
	int u;
	int v;
};
node edge[10005];

int main(){
	scanf("%d%d",&N,&M);
	for(int i=0;i<M;i++){
		scanf("%d%d",&edge[i].u,&edge[i].v);
	}
	scanf("%d",&K);
	for(int i=0;i<K;i++){
		int L;
		set<int> s;
		scanf("%d",&L);
		for(int j=0;j<L;j++){
			int t;
			scanf("%d",&t);
			s.insert(t);
		}
		bool f = true;
		for(int j=0;j<M;j++){
			if(s.find(edge[j].u)!=s.end()){
				continue;
			}
			if(s.find(edge[j].v)!=s.end()){
				continue;
			}
			f = false;
			break;
		}
		if(f){
			printf("Yes\n"); 
		}else{
			printf("No\n");
		}
	}
	return 0;
}

1135 Is It A Red-Black Tree (30 分)

算法标签: 树,二叉树 + DFS
注意点:
1,红黑树的外部结点是值为NULL的黑结点,该结点必须考虑进入黑高度的计算之中,否则会导致判断错误[测试点3]
2.整体思路:建树+DFS遍历
(1) The root is black.
(2) Every leaf (NULL) is black.
(3) If a node is red, then both its children are black.
(4) For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.

#include<bits/stdc++.h>
using namespace std;
int K;
bool flag;
int blackheight;
struct node{
	int data;
	bool red;
	node* lchild;
	node* rchild;
};
node* newnode(int v,int red){
	node* Node = new node;
	Node->data = v;
	Node->red = red;
	Node->lchild = NULL;
	Node->rchild = NULL;
	return Node;
}
void insert(node* &root,int x,bool red){
	if(root == NULL){
		root = newnode(x,red);
		return;
	}
	if(x<root->data){
		insert(root->lchild,x,red);
	}else{
		insert(root->rchild,x,red);
	}
}
void dfs(node* root,int depth,int blacknum){
	if(depth == 0){
		if(root->red == 1){
			flag = false;
			return;
		}
	}
	if(root == NULL){
		if(blacknum+1!= blackheight){
			flag = false;
		}
		return;
	}
	
	if(root->red == 0){
		dfs(root->lchild,depth+1,blacknum+1);
		dfs(root->rchild,depth+1,blacknum+1);
	}else{
		if(root->lchild){
			if(root->lchild->red == 0){
				dfs(root->lchild,depth+1,blacknum);
			}else{
				flag = false;
				return;
			}
		}else{
			dfs(root->lchild,depth+1,blacknum);
		}
		if(root->rchild){
			if(root->rchild->red == 0){
				dfs(root->rchild,depth+1,blacknum);
			}else{
				flag = false;
				return;	
			}
		}else{
			dfs(root->rchild,depth+1,blacknum);
		}
	}
}
int main(){
	scanf("%d",&K);
	for(int i=0;i<K;i++){
		int N;
		scanf("%d",&N);
		node* root = NULL;
		for(int j=0;j<N;j++){
			int u;
			scanf("%d",&u);
			bool red = 0;
			if(u<0){
				red = 1;
			}
			u = abs(u);
			insert(root,u,red);
		}
		flag = true;
		blackheight = 0;
		node* temp = root;
		while(temp){
			if(temp->red == 0){
				blackheight++;
			}
			temp = temp->lchild;
		}
		blackheight++;
		dfs(root,0,0);
		if(flag){
			printf("Yes\n");
		}else{
			printf("No\n");
		}
	}
	return 0;
}

1136 A Delayed Palindrome (20 分)

算法标签: 模拟 + 高精

#include<bits/stdc++.h>
using namespace std;
int a[1050];
int b[1050];
int c[1050];
bool isright(int c[],int len){
	bool flag = true;
	for(int i=0;i<len/2;i++){
		if(c[i] == c[len-i-1]){
			continue;
		}else{
			flag = false;
			break;
		}
	}
	return flag;
}
int main(){
	string s;
	cin >> s;
	
	int len = s.size();
	for(int i=0;i<len;i++){
		a[len-i-1] = s[i] -'0';
		b[i] = s[i] -'0';
	}
	if(isright(a,len)){
		for(int i=len-1;i>=0;i--){
			cout << a[i];
		}
		cout << " is a palindromic number.";
		return 0;
	}
	int lena = len,lenb = len;
	
	for(int j=0;j<10;j++){
		memset(c,0,sizeof(c));
		int jw = 0;
		
		for(int i=0;i<len;i++){
			c[i] = jw + a[i] + b[i];
			jw = c[i] / 10;
			c[i] = c[i] % 10;
		}
		if(jw){
			c[len] = jw; 
			len++;
		}
		
		//print
		for(int i=lena-1;i>=0;i--){
			cout << a[i];
		}
		cout << " + ";
		for(int i=lenb-1;i>=0;i--){
			cout << b[i];
		}
		cout << " = ";
		for(int i=len-1;i>=0;i--){
			cout << c[i];
		}
		cout << endl;
		//
		
		bool f = isright(c,len);
		if(f){
			for(int i=len-1;i>=0;i--){
				cout << c[i];
			}
			cout << " is a palindromic number.";
			return 0;
		}else{
			for(int i=0;i<len;i++){
				a[i] = c[i];
				b[i] = c[len-1-i];
			}
			lena = len;
			lenb = len;
		}
	} 
	
	cout << "Not found in 10 iterations.";
	
	return 0;
}

1137 Final Grading (25 分)

算法标签: 排序 + 结构体

#include<bits/stdc++.h>
using namespace std;
typedef struct student{
	string s;
	int score1;
	int score2;
	int score3;
	int score4;
}stu;
vector<stu> v;
bool cmp(stu s1,stu s2){
	if(s1.score4!=s2.score4){
		return s1.score4>s2.score4;
	}else{
		return s1.s < s2.s;
	} 
}
map<string,int> A;
map<string,int> B;
map<string,int> C;

int main(){
	int P,M,N;
	cin >> P >> M >> N;
	for(int i=0;i<P;i++){
		string s;
		int score;
		cin >> s >> score;
		A[s] = score;
		B[s] = -1;
		C[s] = -1;
	}
	for(int i=0;i<M;i++){
		string s;
		int score;
		cin >> s >> score;
		B[s] = score;
	}
	for(int i=0;i<N;i++){
		string s;
		int score;
		cin >> s >> score;
		C[s] = score;
	}
	for(auto it = A.begin();it!=A.end();it++){
		stu student;
		student.s = it->first;
		student.score1 = it->second;
		student.score2 = B[it->first];
		student.score3 = C[it->first];
		double f;
		if(student.score2!=-1 && student.score3!=-1){
			f = student.score2 * 0.4 + student.score3 * 0.6;
		}else if(student.score2!=-1){
			f = student.score2 * 0.4;
		}else if(student.score3!=-1){
			f = student.score3;
		}else{
			f = 0;
		}
		int f0 = (round)(f);
		if(student.score3>f0){
			student.score4 = student.score3;
		}else{
			student.score4 = f0;
		}
		v.push_back(student);
	}
	sort(v.begin(),v.end(),cmp);
	for(int i=0;i<v.size();i++){
		if(v[i].score1>=200 && v[i].score4>=60){
			cout << v[i].s << " " << v[i].score1 << " " << v[i].score2 << " " << v[i].score3
			<< " " << round(v[i].score4) << endl;
		}
	}
	return 0;
}

1138 Postorder Traversal (25 分)

算法标签: 树,二叉树 + DFS
注意点:
先根据前序遍历和后序遍历建树,然后后序遍历访问树上结点

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
int N;
int pre[maxn];
int in[maxn];

struct node{
	int data;
	node* lchild;
	node* rchild;
};

node* newnode(int v){
	node* Node = new node;
	Node->data = v;
	Node->lchild = NULL;
	Node->rchild = NULL;
	return Node;
}

node* Create(int preL,int preR,int inL,int inR){
	if(preL>preR){
		return NULL;
	}
	node* root = newnode(pre[preL]);
	int k;
	for(int i=inL;i<=inR;i++){
		if(pre[preL] == in[i]){
			k = i;
			break;
		}
	}
	int numleft = k-inL;
	root->lchild = Create(preL+1,preL+numleft,inL,inL+numleft-1);
	root->rchild = Create(preL+numleft+1,preR,inL+numleft+1,inR);
	return root;
}

void PostOrder(node* root){
	while(1){
		while(root->lchild){
			root = root->lchild;
		}
		if(root->rchild){
			root = root->rchild;
		}else{
			break;
		}	
	}
	printf("%d\n",root->data);
}

int main(){
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%d",&pre[i]);
	}
	for(int i=1;i<=N;i++){
		scanf("%d",&in[i]); 
	}
	node* root = Create(1,N,1,N);
	PostOrder(root);
	
	return 0;
} 

1139 First Contact (30 分)

算法标签: 图论 + BFS
注意点:
一道好题!这道题目包含着许多细节:
1.可能出现+0000与-0000元素,-代表女生,+代表男生
2.枚举A的朋友B,再枚举B的朋友C(注意此时不能为A)

#include<bits/stdc++.h>
using namespace std;
vector<int> G[10005];
int hashT[10005];
struct node{
	int friend1;
	int friend2;
};
node out[10005];
bool cmp(node n1,node n2){
	if(n1.friend1!=n2.friend1){
		return n1.friend1 < n2.friend1;
	}else{
		return n1.friend2 < n2.friend2;
	}
}

int main(){
	int N,M;
	scanf("%d%d",&N,&M);
	for(int i=0;i<M;i++){
		string u,v;
		cin >> u >> v;
		if(u[0]=='-'){
			hashT[abs(stoi(u))] = 2;
		}else{
			hashT[abs(stoi(u))] = 1;
		}
		if(v[0]=='-'){
			hashT[abs(stoi(v))] = 2;
		}else{
			hashT[abs(stoi(v))] = 1;
		}
		G[abs(stoi(u))].push_back(abs(stoi(v)));
		G[abs(stoi(v))].push_back(abs(stoi(u)));
	}
	int K;
	scanf("%d",&K);
	for(int i=0;i<K;i++){
		int cnt = 0;
		int u1,u2;
		string s1,s2;
		int flag = 0;
		cin >> s1 >> s2;
		if(s1[0]!='-' && s2[0]=='-'){
			flag = 1;
		}else if(s1[0]=='-' && s2[0]!='-'){
			flag = 2;
		}else if(s1[0]!='-' && s2[0]!='-'){
			flag = 3;
		}else{
			flag = 4;
		}
		u1 = abs(stoi(s1));
		u2 = abs(stoi(s2));
		
		if(flag == 1){
			for(int j=0;j<G[u1].size();j++){
				int v = G[u1][j];
				if(hashT[v] == 1 && v!=u2){
					for(int k=0;k<G[v].size();k++){
						int w = G[v][k];
						if(hashT[w] == 2 && w!=u2){
							bool f = false;
							for(int p=0;p<G[w].size();p++){
								if(G[w][p] == u2){
									f = true;
									break;
								}
							}
							if(f){
								out[cnt].friend1 = v;
								out[cnt].friend2 = w;
								cnt++;
							}
						} 
					}
				}
			}
		}else if(flag == 2){
			for(int j=0;j<G[u1].size();j++){
				int v = G[u1][j];
				if(hashT[v] == 2 && v!=u2){
					for(int k=0;k<G[v].size();k++){
						int w = G[v][k];
						if(hashT[w] == 1 && w!=u2){
							bool f = false;
							for(int p=0;p<G[w].size();p++){
								if(G[w][p] == u2){
									f = true;
									break;
								}
							}
							if(f){
								out[cnt].friend1 = v;
								out[cnt].friend2 = w;
								cnt++;
							}
						} 
					}
				}
			}
		}else if(flag == 3){
			for(int j=0;j<G[u1].size();j++){
				int v = G[u1][j];
				if(hashT[v] == 1 && v!=u2){
					for(int k=0;k<G[v].size();k++){
						int w = G[v][k];
						if(hashT[w] == 1 && w!=u2 && w!=u1){
							bool f = false;
							for(int p=0;p<G[w].size();p++){
								if(G[w][p] == u2){
									f = true;
									break;
								}
							}
							if(f){
								out[cnt].friend1 = v;
								out[cnt].friend2 = w;
								cnt++;
							}
						} 
					}
				}
			}
		}else{
			for(int j=0;j<G[u1].size();j++){
				int v = G[u1][j];
				if(hashT[v] == 2 && v!=u2){
					for(int k=0;k<G[v].size();k++){
						int w = G[v][k];
						if(hashT[w] == 2 && w!=u2 && w!=u1){
							bool f = false;
							for(int p=0;p<G[w].size();p++){
								if(G[w][p] == u2){
									f = true;
									break;
								}
							}
							if(f){
								out[cnt].friend1 = v;
								out[cnt].friend2 = w;
								cnt++;
							}
						} 
					}
				}
			}
		}
		sort(out,out+cnt,cmp);
		printf("%d\n",cnt);
		for(int i=0;i<cnt;i++){
			printf("%04d %04d\n",out[i].friend1,out[i].friend2);
		}
	}
	return 0;
} 

1140 Look-and-say Sequence (20 分)

算法标签: 模拟
注意点: 这是一道找规律的题目,我们需找出图中数字变化的规律,不难发现,每一次都是对前一字符串的压缩,因此反复迭代模拟即可

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e2+5;
string str[maxn];
int main(){
	int d,N;
	cin >> d >> N;
	str[0] += (d+'0');
	for(int i=1;i<N;i++){
		char start = str[i-1][0];
		int count = 0;
		for(int j=0;j<str[i-1].size();j++){
			if(str[i-1][j]==start){
				count++;
			}else{
				str[i] += start;
				str[i] += (count+'0');
				count = 1;
				start = str[i-1][j];
			}
		}
		str[i] += start;
		str[i] += (count+'0');
	}
	cout << str[N-1] << endl;
	return 0;
} 

1141 PAT Ranking of Institutions (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
struct node{
	string name;
	int res;
	int num;
};

unordered_map<string,double> Tscore;
unordered_map<string,int> Man;

bool cmp(node n1,node n2){
	if(n1.res!=n2.res){
		return n1.res>n2.res;
	}else if(n1.num!=n2.num){
		return n1.num<n2.num;
	}else{
		return n1.name < n2.name;
	} 
}

int main(){
	int N;
	cin.tie(0);
	cout.tie(0);
	cin >> N;
	for(int i=0;i<N;i++){
		string number;
		cin >> number;
		int score;
		cin >> score;
		double r;
		
		string sname;
		cin >> sname;
		for(int j=0;j<sname.size();j++){
			sname[j] = tolower(sname[j]);
		}
		if(number[0]=='B'){
			r = score*1.0/1.5; 
		}else if(number[0]=='A'){
			r = score *1.0;
		}else if(number[0]=='T'){
			r = score *1.5;
		} 
		Tscore[sname] += r;
		Man[sname] ++;
	}
	vector<node> ans;
	int ch = 0;
	for(auto it =Tscore.begin();it!=Tscore.end();it++){
		ans.push_back(node{it->first,(int)(it->second),Man[it->first]});
	}
	sort(ans.begin(),ans.end(),cmp);
	int rank = 1;
	double snum=0.0;
	cout << ans.size() << endl;
	for(int i=0;i<ans.size();i++){
		if(snum!=ans[i].res){
			snum = ans[i].res;
			rank = i+1;
		}
		cout << rank << " " << ans[i].name << " " << ans[i].res << " " << ans[i].num << endl;
	}
	
	return 0;
}

1142 Maximal Clique (25 分)

算法标签: 最大团
注意点: 最大团问题,是指在一个无向图中找出一个点数最多的完全图。通俗一点讲,就是找到一个点的集合,使得这些点能够覆盖图中所有的边,因此,我们可以采用枚举的策略,枚举每个点,并标记由该点连通的边,枚举结束后,若所有边全部被覆盖,则这些顶点组成的集合是一个最大团,否则就不是

#include<bits/stdc++.h>
using namespace std;

int G[205][205];
int a[205];
bool hashT[205];

int main(){
	int Nv,Ne;
	scanf("%d%d",&Nv,&Ne);
	for(int i=1;i<=Ne;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u][v] = G[v][u] = 1;
	}
	int M;
	scanf("%d",&M);
	for(int i=1;i<=M;i++){
		memset(hashT,0,sizeof(hashT));
		int K;
		scanf("%d",&K);
		for(int j=1;j<=K;j++){
			scanf("%d",&a[j]);
			hashT[a[j]] = true;
		}
		bool isfriend = true;
		for(int j=1;j<=K-1;j++){
			for(int k=j+1;k<=K;k++){
				if(G[a[j]][a[k]]){
					continue;
				}else{
					isfriend = false;
					break;
				}
			}
		}
		
		if(!isfriend){
			printf("Not a Clique\n");
		}else{
			bool isall = true;
			for(int j=1;j<=Nv;j++){
				if(!hashT[j]){
					bool exist = true;
					for(int k=1;k<=K;k++){
						if(G[j][a[k]]){
							continue;
						}else{
							exist = false;
							break;
						}
					}
					if(exist){
						isall = false;
						break;
					}
				}
			}
			if(isall){
				printf("Yes\n");
			}else{
				printf("Not Maximal\n");
			}
		}
	}
	return 0;
} 

1143 Lowest Common Ancestor (30 分)

算法标签: 树,二叉树 + LCA
注意点: LCA模板题,考虑到本题的样例数据规模较小,因此,我们采用DFS回溯法求公共祖先,也即从根结点出发,DFS遍历出两条路径,而路径的最大公共前缀末尾即为最小公共祖先的结点,输出即可,若查询不到该结点,则输出error。
当然,求解最小公共祖先结点的正解是倍增LCA算法或Tarjan算法,该算法在数据结构专题系列-LCA中给出

#include<bits/stdc++.h>
using namespace std;
int M,N;
int pre[10005];
int in[10005];
int path1[10005];
int path2[10005];
int cnt1 = 0;
int cnt2 = 0;

struct node{
	int data;
	node* lchild;
	node* rchild;
};
node* newnode(int v){
	node* Node = new node;
	Node->data = v;
	Node->lchild = NULL;
	Node->rchild = NULL;
	return Node;
}
node* Create(int preL,int preR,int inL,int inR){
	if(preL>preR){
		return NULL;
	}
	node* root = newnode(pre[preL]);
	int k;
	for(int i=inL;i<=inR;i++){
		if(pre[preL] == in[i]){
			k = i;
			break;
		}
	}
	int numleft = k-inL;
	root->lchild = Create(preL+1,preL+numleft,inL,inL+numleft-1);
	root->rchild = Create(preL+numleft+1,preR,inL+numleft+1,inR);
	return root;
}

int search1(node* root,int v){
	if(root == NULL){
		return 0;
	}
	if(root->data == v){
		path1[cnt1++] = v;
		return 1;
	}else if(v<root->data){
		path1[cnt1++] = root->data;
		search1(root->lchild,v);
	}else{
		path1[cnt1++] = root->data;
		search1(root->rchild,v);
	}
}
int search2(node* root,int v){
	if(root == NULL){
		return 0;
	}
	if(root->data == v){
		path2[cnt2++] = v;
		return 1;
	}else if(v<root->data){
		path2[cnt2++] = root->data;
		search2(root->lchild,v);
	}else{
		path2[cnt2++] = root->data;
		search2(root->rchild,v);
	}
}

int main(){
	scanf("%d%d",&M,&N);
	node* root = NULL;
	for(int i=1;i<=N;i++){
		scanf("%d",&pre[i]);
		in[i] = pre[i];
	}
	sort(in+1,in+1+N);
	root = Create(1,N,1,N);
	for(int i=1;i<=M;i++){
		int U,V;
		scanf("%d%d",&U,&V);
		cnt1 = 0;
		cnt2 = 0;
		int f1 = search1(root,U);
		int f2 = search2(root,V);
		if(!f1 && !f2){
			printf("ERROR: %d and %d are not found.\n",U,V);
		}else if(!f1 && f2){
			printf("ERROR: %d is not found.\n",U);
		}else if(f1 && !f2){
			printf("ERROR: %d is not found.\n",V);
		}else{
			int k = -1;
			bool f = false;
			for(int i=0;i<cnt1 && i<cnt2;i++){
				if(path1[i] == path2[i]){
					f = true;
					continue;
				}else{
					k = i-1;
					break;
				}
			}
			if(f && k==-1){
				k = min(cnt1,cnt2)-1;
			}
			if(path1[k] == U){
				printf("%d is an ancestor of %d.\n",U,V);
			}else if(path1[k] == V){
				printf("%d is an ancestor of %d.\n",V,U);
			}else{
				printf("LCA of %d and %d is %d.\n",U,V,path1[k]);
			}
		}
	}
	return 0;
} 

1144 The Missing Number (20 分)

算法标签: 哈希

#include<bits/stdc++.h>
using namespace std;
bool hashT[100005];

int main(){
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		int t;
		scanf("%d",&t);
		if(t>100000 || t<=0){
			continue;
		}else{
			hashT[t] = true; 
		}
	}
	int res=N+1;
	for(int i=1;i<=N;i++){
		if(!hashT[i]){
			res = i;
			break;
		}
	}
	printf("%d\n",res);
	return 0;
}

1145 Hashing - Average Search Time (25 分)

算法标签: 哈希
注意点: 本题考察对哈希冲突算法的理解,题目中给出的实现方法是开放定址法,哈希函数为除模取余法,冲突解决的方案为平方试探法(单向),模拟哈希表的处理过程即可

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e4+50;
bool p[maxn]={1,1,0};
int a[maxn];
int hashT[maxn];
int msize;
int N,M;
int Tsize;

void init(){
	for(int i=2;i<maxn;i++){
		if(!p[i]){
			for(int j=2*i;j<maxn;j+=i){
				p[j] = 1;
			}
		}
	}
}

int main(){
	init();
	scanf("%d%d%d",&msize,&N,&M);
	
	for(int i=0;i<N;i++){
		scanf("%d",&a[i]);
	}
	
	if(!p[msize]){
		Tsize = msize;
	}else{
		for(int i=msize+1;;i++){
			if(!p[i]){
				Tsize = i;
				break;
			}
		}
	}
	
	for(int i=0;i<N;i++){
		int key = a[i] % Tsize;
		if(!hashT[key]){
			hashT[key] = a[i];
		}else{
			bool f = false;
			for(int step=1;step<Tsize;step++){
				int k = (a[i]+step*step)%Tsize;
				if(!hashT[k]){
					hashT[k] = a[i];
					f = true;
					break;
				}
			} 
			if(!f){
				printf("%d cannot be inserted.\n",a[i]);
			}
		}
	}
	int sum = 0;
	for(int i=0;i<M;i++){
		int t;
		scanf("%d",&t);
		int key = t % Tsize;
		sum++;
		if(hashT[key] == t || hashT[key] == 0){
			continue;
		}else{
			bool f = false;
			for(int step=1;step<Tsize;step++){
				int k = (t+step*step)%Tsize;
				sum++;
				if(hashT[k]==t || hashT[k] == 0){
					f = true;
					break;
				}
			}
			if(!f){
				sum++;
			}
		}
	}
	double res = (sum*1.0)/(M*1.0);
	printf("%.1lf\n",res);
	
	return 0;
} 

1146 Topological Order (25 分)

算法标签: 图论 + 拓扑排序
注意点: 拓扑排序的验证题,本题要求验证一串序列是否为拓扑排序,验证的过程如下:根据题目输入的序列顺序,依次抹去对应的结点及其出边,删除结点时需检验结点的入度为0,否则不是拓扑序列,若所有的结点都能正常删除,记录此次输入是拓扑序列

#include<bits/stdc++.h>
using namespace std;
int N,M,K;
int a[1005];
int b[1005];
vector<int> G[1005];
int indegree[1005];
vector<int> ans;

void init(){
	for(int i=1;i<=N;i++){
		a[i] = indegree[i];
	}
}
int main(){
	scanf("%d%d",&N,&M);
	for(int i=1;i<=M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		indegree[v]++;
	}
	scanf("%d",&K);
	for(int i=0;i<K;i++){
		init();
		for(int j=1;j<=N;j++){
			scanf("%d",&b[j]);
		}
		for(int j=1;j<=N;j++){
			if(!a[b[j]]){
				for(int k=0;k<G[b[j]].size();k++){
					int v = G[b[j]][k];
					a[v]--;
				}
			}else{
				ans.push_back(i);
				break;
			}
		}
	}
	
	for(int i=0;i<ans.size();i++){
		if(i==0){
			printf("%d",ans[i]);
		}else{
			printf(" %d",ans[i]);
		}
	}
	return 0;
} 

1147 Heaps (30 分)

算法标签:
注意点: 本题考察堆的概念,堆是指一个有序的二叉树,根结点与左右子树之间都维持着某种顺序,因此,本题首先要判断输入的序列是否为堆,通过DFS遍历即可得出;若是堆,还需判断是大根堆还是小根堆,我们可直接判断根结点的顺序,其余的结点必定是满足这个顺序的

#include<bits/stdc++.h>
using namespace std;
int M,N;
int a[2005];
int path[2005];
int cnt = 0;
void dfs(int root){
	if(root>N){
		return;
	}
	dfs(root*2);
	dfs(root*2+1);
	if(!cnt){
		printf("%d",a[root]);
	}else{
		printf(" %d",a[root]);
	}
	cnt++;
}

int isheap(int root){
	bool f = false;
	if(a[root*2]>a[root] && a[root*2+1]>a[root]){
		f = true;
	}else if(a[root*2]<a[root] && a[root*2+1]<a[root]){
		f = false;
	}else{
		return -1;
	}
	int i = root;
	int j = 2*i;
	while(j<=N){
		if(j+1<=N){
			if(a[j]>a[i] && a[j+1]>a[i] && f){
				i++;
				j = i*2;
			}else if(a[j]<a[i] && a[j+1]<a[i] && !f){
				i++;
				j = i*2;
			}else{
				return -1;
			}
		}else if(j<=N){
			if(a[j]>a[i] && f){
				i++;
				j = i*2;
			}else if(a[j]<a[i] && !f){
				i++;
				j = i*2;
			}else{
				return -1;
			}
		}
	}
	
	if(f){
		return 0;
	}else{
		return 1;
	}
}

int main(){
	scanf("%d",&M);
	scanf("%d",&N);
	for(int p=0;p<M;p++){
		for(int i=1;i<=N;i++){
			scanf("%d",&a[i]); 
		}
			int res = isheap(1);
			if(res == -1){
				printf("Not Heap\n");
			}else if(res == 0 ){
				printf("Min Heap\n");
			}else{
				printf("Max Heap\n");
			}
			cnt = 0;
			dfs(1);
			printf("\n");
	}
	
	return 0;
} 

1148 Werewolf - Simple Version (20 分)

算法标签: 模拟

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e2+5;
int a[maxn];
int c[maxn];

int main(){
	int N;
	cin >> N;
	for(int i=1;i<=N;i++){
		cin >> a[i];
	}
	for(int i=1;i<=N-1;i++){
		for(int j=i+1;j<=N;j++){
			for(int k=1;k<=N;k++){
				if(k==i || k==j){
					c[k] = -1;
				}else{
					c[k] = 1;
				}
			}
			
			vector<int> l;
			for(int k=1;k<=N;k++){
				if(a[k]<0 && abs(a[k])!=i && abs(a[k])!=j){
					l.push_back(k);
				}else if(a[k]>0 && (a[k]==i || a[k]==j)){
					l.push_back(k);
				}
			}
			if(l.size()==2 && (c[l[0]]+c[l[1]]==0)){
				cout << i << " " << j << endl;
				return 0;
			}
		}
	} 
	cout << "No Solution" << endl;
	return 0;
} 

1149 Dangerous Goods Packaging (25 分)

算法标签: 模拟

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int c[maxn];
unordered_map<int,vector<int>> good;

int main(){
	int N,M;
	cin.tie(0);
	cout.tie(0);
	cin >> N >> M;
	for(int i=0;i<N;i++){
		int g1,g2;
		cin >> g1 >> g2;
		good[g1].push_back(g2);
		good[g2].push_back(g1);
	}
	for(int i=0;i<M;i++){
		int K;
		cin >> K;
		memset(a,0,sizeof(a));
		bool flag = false;
		for(int j=0;j<K;j++){
			cin >> c[j];
			a[c[j]] = 1;
		}
		for(int j=0;j<K;j++){
			for(int k=0;k<good[c[j]].size();k++){
				if(!a[good[c[j]][k]]){
					continue;
				}else{
					flag = true;
					break;
				}
			}
			if(flag){
				break;
			}
		}
			
		if(flag){
			cout << "No" << endl;
		}else{
			cout << "Yes" << endl;
		}
	}
	
	return 0;
}

1150 Travelling Salesman Problem (25 分)

算法标签: 图论 + TSP
注意点: TSP问题,又称为旅行商问题,是指一个旅行商需要游历所有的城市一遍并返回起点。本题需要判断输入的序列是否为TSP路径
首先,我们先检查输入的序列,起点和终点是否相同,若不相同,肯定不是TSP路径,接着,我们遍历整个数组,用哈希表统计每个元素的出现情况,若不能覆盖所有顶点,也不是TSP路径;进一步的,我们考察每个路径相邻的顶点对,若两点相连的路径不是图中的连通路,那么也不是TSP路径。
当路径是TSP路径时,我们考察其为简单路径还是复杂路径,简单路径意味着顶点的数量为N+1,复杂路径意味着顶点数要比N+1多

#include<bits/stdc++.h>
using namespace std;
int N,M;
int K;
int G[205][205];
int hashT[205];
int a[10005];

int main(){
	scanf("%d%d",&N,&M);
	for(int i=0;i<M;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		G[u][v] = G[v][u] = w;
	}
	scanf("%d",&K);
	int shortdis = INT_MAX;
	int shortnum;
	for(int i=1;i<=K;i++){
		memset(hashT,0,sizeof(hashT));
		int n;
		scanf("%d",&n);
		for(int j=0;j<n;j++){
			scanf("%d",&a[j]);
			hashT[a[j]]++;
		}
		bool iscycle = true;
		int total = 0;
		for(int j=0;j<n-1;j++){
			int u = a[j];
			int v = a[j+1];
			if(G[u][v]>0){
				total += G[u][v];
			}else{
				iscycle = false;
				total = -1;
				break;
			}
		}
		for(int j=1;j<=N;j++){
			if(hashT[j]){
				continue;
			}else{
				iscycle = false;
				break;
			}
		}
		if(a[0]!=a[n-1]){
			iscycle = false;
		}
		if(!iscycle){
			if(total == -1){
				printf("Path %d: NA (Not a TS cycle)\n",i);
			}else{
				printf("Path %d: %d (Not a TS cycle)\n",i,total);
			}
		}else{
			if(n == N+1){
				printf("Path %d: %d (TS simple cycle)\n",i,total);
			}else{
				printf("Path %d: %d (TS cycle)\n",i,total);
			}
			if(shortdis > total){
				shortdis = total;
				shortnum = i;
			}
		}
	}
	printf("Shortest Dist(%d) = %d\n",shortnum,shortdis);
	return 0;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,CSP-J2021复赛有两道题目,分别是分糖果和小熊的果篮。 对于第一题分糖果,题目来源是CCF,难度为入门。根据给出的代码,这是一个基于循环的算法,通过遍历[l,r]区间内的数,计算数对n取模后的最大值。具体的实现细节可以参考引用中的代码。这道题目属于入门别,比较简单。 第二题是关于小熊的果篮。给定一个长度为n的数组a,其中连续的相同元素被视为一个块,要求按照块的顺序输出每个块的头元素,并删除已输出的元素。具体的实现细节可以参考引用中的代码。这道题目需要使用双链表来处理,时间复杂度为O(n)。 综上所述,CSP-J2021复赛的题目包括分糖果和小熊的果篮,具体的解题思路和代码实现可以参考上述引用内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [[CSP-J 2021]比赛题解](https://blog.csdn.net/weixin_56550385/article/details/126811201)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [新鲜出炉的 CSP-J 2021 复赛题目 题解](https://blog.csdn.net/qq_23109971/article/details/121024436)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值