上午看了二叉树的一些题,发现不会写题。又继续看大话数据结构
下午学长讲二叉树的前,中,后序遍历,建立。还有知道前中序,推出后序等。然后这个貌似还是不会写。
晚上在洛谷写了一道新二叉树,两道并查集题。
题目描述
输入一串二叉树,输出其前序遍历。
输入格式
第一行为二叉树的节点数 nn。(1 \leq n \leq 261≤n≤26)
后面 nn 行,每一个字母为节点,后两个字母分别为其左右儿子。
空节点用
*
表示输出格式
二叉树的前序遍历。
输入输出样例
输入 #1复制
6 abc bdi cj* d** i** j**输出 #1复制
abdicj
思路:只有26个字母,可以用数组来表示所在的结点,用两个数组各来表示它是否出现过和它是不是根结点(它是不是某个节点的左右儿子),最后找到根结点,然后前序遍历
#include<stdio.h>
int n;
int b[26]={0},c[26]={0};
struct node
{
char l,r;
}tree[26];
void creat(char root,char left,char right)
{
c[root-'a']=1;//标记它出现过了
if(left!='*'){
tree[root-'a'].l=left;
b[left-'a']=1;//标记它不是根节点
c[left-'a']=1;//标记它出现过了
}
else tree[root-'a'].l='*';
if(right!='*'){
tree[root-'a'].r=right;
b[right-'a']=1;
c[left='a']=1;
}
else tree[root-'a'].r='*';
}
void Pretree(char root)//前序遍历
{
if(root!='*'){
printf("%c",root);
Pretree(tree[root-'a'].l);
Pretree(tree[root-'a'].r);
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++){
char a[4];
scanf("%s",a);
creat(a[0],a[1],a[2]);
}
for(int i=0;i<27;i++){
if(b[i]==0&&c[i]==1){//遍历找到根节点
Pretree(i+'a');
break;
}
}
printf("\n");
}
题目背景
小明在 A 公司工作,小红在 B 公司工作。
题目描述
这两个公司的员工有一个特点:一个公司的员工都是同性。
A 公司有 NN 名员工,其中有 PP 对朋友关系。B 公司有 MM 名员工,其中有 QQ 对朋友关系。朋友的朋友一定还是朋友。
每对朋友关系用两个整数 (X_i,Y_i)(Xi,Yi) 组成,表示朋友的编号分别为 X_i,Y_iXi,Yi。男人的编号是正数,女人的编号是负数。小明的编号是 11,小红的编号是 -1−1。
大家都知道,小明和小红是朋友,那么,请你写一个程序求出两公司之间,通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。
输入格式
输入的第一行,包含 44 个空格隔开的正整数 N,M,P,QN,M,P,Q。
之后 PP 行,每行两个正整数 X_i,Y_iXi,Yi。
之后 QQ 行,每行两个负整数 X_i,Y_iXi,Yi。
输出格式
输出一行一个正整数,表示通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。
输入输出样例
输入 #1复制
4 3 4 2 1 1 1 2 2 3 1 3 -1 -2 -3 -3输出 #1复制
2说明/提示
对于 30 \%30% 的数据,N,M \le 100N,M≤100,P,Q \le 200P,Q≤200;
对于 80 \%80% 的数据,N,M \le 4 \times 10^3N,M≤4×103,P,Q \le 10^4P,Q≤104;
对于 100 \%100% 的数据,N,M \le 10^4N,M≤104,P,Q \le 2 \times 10^4P,Q≤2×104。
先找出小红有多少个朋友,再找出小明有多少朋友,朋友少的那个就是最多情侣对。
#include<stdio.h>
#include<math.h>
int N,M,P,Q;
int f[10000];
int getf(int v)
{
if(f[v]==v) return v;
else{
f[v]=getf(f[v]);//路径压缩
return f[v];
}
}
void merge(int x,int y)
{
int t1,t2;
t1=getf(x);
t2=getf(y);
if(t1!=t2){
f[t2]=t1;
}
return;
}
int main()
{
int s1=0,s2=0;
scanf("%d%d%d%d",&N,&M,&P,&Q);
for(int i=1;i<=N;i++)
f[i]=i;
for(int i=0;i<P;i++){
int x,y;
scanf("%d%d",&x,&y);
merge(x,y);
}
int t=getf(1);
for(int i=1;i<=N;i++)
if(getf(f[i])==t) s1++;
for(int i=1;i<=M;i++)
f[i]=i;
for(int i=0;i<Q;i++){
int x,y;
scanf("%d%d",&x,&y);
merge(abs(x),abs(y));
}
t=getf(1);
for(int i=1;i<=M;i++)
if(getf(f[i])==t) s2++;
if(s1>s2) printf("%d\n",s2);
else printf("%d",s1);
//printf("%d %d\n",s1,s2);
}
题目背景
AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。
题目描述
给出A地区的村庄数NN,和公路数MM,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)
输入格式
第11行两个正整数N,MN,M
下面MM行,每行33个正整数x, y, tx,y,t,告诉你这条公路连着x,yx,y两个村庄,在时间t时能修复完成这条公路。
输出格式
如果全部公路修复完毕仍然存在两个村庄无法通车,则输出-1−1,否则输出最早什么时候任意两个村庄能够通车。
输入输出样例
输入 #1复制
4 4 1 2 6 1 3 4 1 4 5 4 2 3输出 #1复制
5说明/提示
N \le 1000,M \le 100000N≤1000,M≤100000
x \le N,y \le N,t \le 100000x≤N,y≤N,t≤100000
思路:先将时间从小到大排序,然后开始合并,遇到两个村不通的就合并然后路的条数+1,如果两个村可以通就不管它,当路等于N-1就说明都通了,否则就没通。
#include<stdio.h>
struct node
{
int x,y,t;
}a[100001],w;
int N,M;
int f[100001];
void qs(int l,int r)//快排
{
int mid=a[(l+r)/2].t;
// printf("%d\n",mid);
int i=l,j=r;
while(i<=j){
while(a[i].t<mid) i++;
while(a[j].t>mid) j--;
if(i<=j){
w=a[i];
a[i]=a[j];
a[j]=w;
i++;
j--;
}
}
if(i<r) qs(i,r);
if(j>l) qs(l,j);
}
int getf(int v)
{
if(f[v]==v) return v;
else{
f[v]=getf(f[v]);//路径压缩
return f[v];
}
}
int merge(int x,int y)
{
int t1,t2;
t1=getf(x);
t2=getf(y);
if(t1!=t2){//这两个村庄的'祖先'不同
f[t2]=t1;
return 1;
}
else return 0;
}
int main()
{
int s=0,flag=0,T;
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
f[i]=i;
for(int i=1;i<=M;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].t);
qs(1,M);
// for(int i=1;i<=M;i++)
// printf("%d %d %d\n",a[i].x,a[i].y,a[i].t);
for(int i=1;i<=M;i++){
if(merge(a[i].x,a[i].y)==1){
s++;
T=a[i].t;
}
if(s==N-1) {flag=1;break;}//只需N-1条路就行了
}
if(flag==1) printf("%d\n",T);
else printf("-1\n");
}
明天二叉树推导遍历结果。