作业H6-图和树的性质与应用(上)

1.元音跳跃

样例输入

10
aeioubaeio




样例输出

5

详解:

水题。直接记录元音的个数,碰到辅音就记下cnt与ans的较大值,并将cnt值赋0,遍历一遍字符串即可。

#include<bits/stdc++.h>
using namespace std;
int fun(char x){
    if(x=='a'||x=='e'||x=='i'||x=='o'||x=='u')
        return 1;
    else return 0;
}
int main(){
    int n;
    string str;
    cin>>n;
    cin>>str;
    int ans=0,cnt=0;//ans为最终答案,cnt为当前连续元音个数
    for(int i=0;i<n;i++){
        if(fun(str[i])){
            cnt++;
        }
        else{
            ans=max(cnt,ans);
            cnt=0;
        }
    }
    cout<<ans;
};

2.元音删除

样例输入

11
aeioubaeiou



样例输出

aba

详解:

水题。仅需将碰到的第一个元音存入结果数组中,使用一个判断变量cnt,如果cnt为0,则该元音为第一个,否则不是第一个。如果碰到辅音,则将cnt置0。

#include<bits/stdc++.h>
using namespace std;
int fun(char x){
    if(x=='a'||x=='e'||x=='i'||x=='o'||x=='u')
        return 1;
    else return 0;
}
char ans[1000010];
int main(){
    int n;
    string str;
    cin>>n;
    cin>>str;
    int cnt=0,t=0;//cnt用于判断是否为第一个元音
    for(int i=0;i<n;i++){
        if(fun(str[i])){
            if(cnt==0){//判断为第一个元音,则存入结果数组
                cnt++;
                ans[t++]=str[i];
            }
        }
        else{//判断为辅音,则将cnt置0
            cnt=0;
            ans[t++]=str[i];
        }
    }
    for(int i=0;i<t;i++) cout<<ans[i];
};

3.公路修建

样例输入

5 5
1 1
1 2
2 3
4 4
1 2


样例输出

4
3
2
2
2

详解:

本题考察并查集的基本用法。每次添加一条边,即将两个节点加入同一个并查集。开始时需要的最小公路数为n-1,使用cnt记录并查集中的边数,每加入一条公路,先判断连接的两个节点是否在同一个并查集中,如果不在,则cnt++,否则不处理。每次输出n-1-cnt即为答案。

#include<bits/stdc++.h>
using namespace std;
int fa[100010];
int n,m;
void init(){
    for(int i=1;i<=n;i++)
        fa[i]=i;
}
int find(int x){
    if(x==fa[x]) return x;
    else return fa[x]=find(fa[x]);
}
void union1(int x,int y){
    x=find(x);
    y=find(y);
    if(x!=y) fa[y]=x;
}
int main(){
    cin>>n>>m;
    int cnt=0,ans=n-1;
    init();
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        if(find(x)!=find(y)){
            cnt++;
            union1(x,y);
        }
        cout<<ans-cnt<<endl;
    }
}

4.网络铺设

 

样例输入

5
5 1
1 2
2 3
3 4

样例输出

3 2 3 4 4

详解: 本题考查树的直径。

距离树上点最远的点一定是直径两个点中的一个,所以本题只需要先用两遍bfs求出直径的两个点,再分别从这两个点开始bfs,记录下每个点到它们的距离,最后取大的作为结果。

注意:在每一次bfs前,vis和step数组都要清空。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int u,v,nxt;
}edge[1000010];
int head[1000010],tot,n,vis[1000010],step[1000010],step1[1000010];
void add(int u,int v){
    tot++;
    edge[tot].nxt=head[u];
    edge[tot].u=u;
    edge[tot].v=v;
    head[u]=tot;
}
void bfs(int s){
    queue<int> q;
    q.push(s);
    vis[s]=1;
    step[s]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=head[x];i!=0;i=edge[i].nxt){
            int v=edge[i].v;
            if(vis[v]==0){
                q.push(v);
                vis[v]=1;
                step[v]=step[x]+1;
            }
        }
    }
}
int main(){
    cin>>n;
    for(int i=0;i<n-1;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);
        add(b,a);
    }
    bfs(1);//第一遍dfs找直径的一个点
    int id,max1=0;
    for(int i=1;i<=n;i++){
        if(step[i]>max1){
            max1=step[i];
            id=i;
        }
    }
    memset(vis,0,sizeof(vis));//bfs前记得把相关数组清零
    memset(step,0,sizeof(step));
    bfs(id);//第二遍bfs找直径的另一个点
    for(int i=1;i<=n;i++) step1[i]=step[i];//将从直径一个点出发的遍历结果保存下来
    max1=0;
    for(int i=1;i<=n;i++){
        if(step[i]>max1){
            max1=step[i];
            id=i;
        }
    }
    memset(vis,0,sizeof(vis));
    memset(step,0,sizeof(step));
    bfs(id);//从直径另一个点开始遍历
    //step和step1分别储存直径的两个点到每个点的距离
    for(int i=1;i<=n;i++) cout<<max(step[i],step1[i])<<' ';
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值