山东大学计算机科学与技术学院程序设计思维与实践作业 week6-图和树的性质与应用(上)

山东大学计算机科学与技术学院程序设计思维与实践作业
山大程序设计思维与实践作业
sdu程序设计思维与实践
山东大学程序设计思维实践作业H6
山大程序设计思维实践作业H6
山东大学程序设计思维与实践
week6-图和树的性质与应用(上)

相关资料:GitHub

A : 元音跳跃

问题描述
现在有一个长度为 n 的字符串,都有小写字母组成。
输出最长的连续元音的长度

输入格式
第一行一个整数 n , 0≤n≤10
6

接下来一行表示字符串

输出格式
输出一行,一个数,代表答案

样例输入
10
aeioubaeio
样例输出
5

5

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

int main(){
    int n;
    cin>>n;
    string hang;
    cin>>hang;
    int sum=0,result=0;
    for(int i=0;i<n;i++){
        if(hang[i]=='a' || hang[i]=='e'|| hang[i]=='i' || hang[i] == 'o' || hang[i] == 'u'){
            sum++;
        }
        else{
            if(sum>result)
                result = sum;
                sum = 0;
        }
    }
    cout<<result;
    return 0;
}

B : 元音删除

问题描述
现在有一个长度为 n 的字符串,都有小写字母组成。
现在要将所有相连的元音只保留第一个,并将其他元音删除

输出删除完之后的字符串

输入格式
第一行一个整数 n , 0≤n≤10
6

接下来一行表示字符串

输出格式
输出一行,一个字符出

样例输入
11
aeioubaeiou
样例输出
aba

#include<iostream>
using namespace std;
#include<string>
#include<algorithm>
#include<vector>


bool is_vowel(char c) {
	if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
		return 1;
	}
	return 0;
}
int main() {
	int n;
	cin >> n;
	string str;
	cin >> str;
	vector<char> re;
	bool flag = 0;
	for (int i = 0; i < n; i++) {
		if (is_vowel(str[i]) && flag == 0) {//是元音并且前面没有元音
			re.push_back(str[i]);
			flag = 1;
		}
		if (!is_vowel(str[i])) {
			re.push_back(str[i]);
			flag = 0;
		}
	}
	for (auto it = re.begin(); it != re.end(); it++) {
		cout << *it;
	}
	cout << endl;
}

C : 公路修建

问题描述
你现在是城市的主人
现在有 n 个村庄,要修建 m 条路,每修建一条路,道路是双向的,输出至少还需要修建几条,可以让所有村庄互相可达。
一开始路为 0 条
数据保证有解

输入格式
第一行两个整数 n,m , 0≤n,m≤105 接下来有 m 行,每行 a,b 代表修建了一条从第 a 个村庄,到第 b 个村庄的路。 1≤a,b≤n
a 和 b 可能相同。

输出格式
一共 m 行,第 i 个数代表已经修建了前 i 条路时,最少还需要修建几条,可以让所有村庄互相可达。

样例输入
5 5
1 1
1 2
2 3
4 4
1 2

样例输出
4
3
2
2
2

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

int pa[100001]={-1};
int chazhao(int x){ //查询x所在集合的代表元,其中会进行路径压缩
    if(x == pa[x])  //到达根
        return x;
    return pa[x] = chazhao(pa[x]);
}

//构建并查集,并输出现阶段并查集的个数
bool unite(int a, int b){ //返回值是合并是否成功
    a = chazhao(a); //找到代表元素
    b = chazhao(b);
    if (a == b)   //合并失败,两个集合是同一个
        return false;
    pa[a] = b ;// pa[b] = a;  //合并集合,即将一个挂到另一个
    return true;
}

int main()
{
	int a,b,n,m;
	cin>>n;
	cin>>m;
	for(int i=0;i<n;i++)
	{
		pa[i]=i;
	}
	int result=n-1;
	for(int i=0;i<m;i++)
	{
		cin>>a;
	   cin>>b;
		if(unite(a,b))
		{
			result--;			
		}
		cout<<result<<endl;
	}
}

D : 网络铺设

问题描述
你现在是城市的主人
现在有 n 个村庄,已经修建了 n−1 条道路,使得各个村庄作为节点,路作为边,构成一棵树。
假设第 a 个村庄到第 b 个村庄有路相连,则从 a 走到 b 或者从 b 走到 a 需要走 1m 。
你需要输出 n 个数,第 i 个数代表从第 i 个村庄出发,距离他最远的村庄的距离

输入格式
第一行一个整数 n , 0≤n≤105 接下来有 n−1 行,每行 a,b 代表第 a 个村庄,到第 b 个村庄有一条路。 1≤a,b≤105
保证输入结构是一棵树

输出格式
输出一行 n 个数,表示答案

样例输入
5
5 1
1 2
2 3
3 4

样例输出
3 2 3 4 4

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

set<pair<int,int>> st[(int)2e5];
bool vis[(int)2e5];
int res_1[(int)2e5];
int res_2[(int)2e5];
int pnt1;
int pnt2;

queue<pair<int,int>> qq;

void bfs_1(int x)
{
    memset(vis, 0, sizeof(vis));
    vis[x] = true;
    auto it = st[x].begin();
    while(it!=st[x].end())
    {
        if(!vis[(*it).second])
        {
            qq.push(*it);
            vis[(*it).second] = true;
        }
        it++;
    }
    while(!qq.empty())
    {
        auto y = qq.front();
        pnt1 = y.second;
        qq.pop();
        auto it2 = st[y.second].begin();
        while(it2!=st[y.second].end())
        {
            if(!vis[(*it2).second])
            {
                qq.push(*it2);
                vis[(*it2).second] = true;
            }
            it2++;
        }
    }
}

void bfs_2(int x)
{
    memset(vis, 0, sizeof(vis));
    vis[x] = true;
    auto it = st[x].begin();
    while(it!=st[x].end())
    {
        if(!vis[(*it).second])
        {
            qq.push(*it);
            vis[(*it).second] = true;
            res_1[(*it).second] = 1;
        }
        it++;
    }
    while(!qq.empty())
    {
        auto y = qq.front();
        pnt2 = y.second;
        qq.pop();
        auto it2 = st[y.second].begin();
        while(it2!=st[y.second].end())
        {
            if(!vis[(*it2).second])
            {
                qq.push(*it2);
                vis[(*it2).second] = true;
                res_1[(*it2).second] = res_1[it2->first]+1;
            }
            it2++;
        }
    }
}

void bfs_3(int x)
{
    memset(vis, 0, sizeof(vis));
    vis[x] = true;
    auto it = st[x].begin();
    while(it!=st[x].end())
    {
        if(!vis[(*it).second])
        {
            qq.push(*it);
            vis[(*it).second] = true;
            res_2[(*it).second] = 1;
        }
        it++;
    }
    while(!qq.empty())
    {
        auto y = qq.front();
        pnt2 = y.second;
        qq.pop();
        auto it2 = st[y.second].begin();
        while(it2!=st[y.second].end())
        {
            if(!vis[(*it2).second])
            {
                qq.push(*it2);
                vis[(*it2).second] = true;
                res_2[(*it2).second] = res_2[it2->first]+1;
            }
            it2++;
        }
    }
}

int main()
{
    int n;
    cin>>n;
    memset(res_1,0xfffffff, sizeof(res_1));
    memset(res_2,0xfffffff, sizeof(res_2));
    for(int i = 1;i<=n-1;i++)
    {
        int u;
        int v;
        cin>>u;
	   cin>>v;
        st[u].insert(pair<int,int>{u,v});
        st[v].insert(pair<int,int>{v,u});
    }
    bfs_1(1);
    bfs_2(pnt1);
    bfs_3(pnt2);
    for(int i = 1;i<=n;i++)
    {
        cout<<max(res_1[i],res_2[i])<<" ";
    }
    //system("pause");

    return 0;
}

E : 水渠设计

问题描述
你现在是城市的主人
现在有 n 个田地需要灌溉。
可以选择修建 m 个引水渠,第 i 条从第 a 个田地到第 b 个田地,花费 c 元。
现在可以买任意多个抽水机,买一个抽水机需要花费 p 元。如果在一个田地旁边安置一个抽水机,则该田地会被灌溉。
水可以顺着水渠流动。
求让每一块田地都能被灌溉的最小花费。

输入格式
第一行三个整数 n,m,p , 0≤n,m≤105,p≤109 接下来有 m 行,每行 a,b,c 代表修建了一条从第 a 个田地,到第 b 个田地的水渠,花费 c 元。 1≤a,b≤n,c<=109

输出格式
输出一个数表示答案。

样例输入
5 5 2
1 2 1
2 3 3
3 4 5
1 3 2
1 4 1

样例输出
8

#include<bits/stdc++.h>
using namespace std;
const long long maxnumber=1e6;
const long long maxme=1e6;
long long n,m,to= 0;
struct Edge{
	long long u,v;
	long long w;
	bool operator < (const Edge &p) const{
		return w<p.w;
	}
}E[maxme];

long long pa[maxnumber];
void init()
{
	for(long long i=0;i<=n;i++) pa[i]=i;
}
long long chazhao(long long x)
{
	return pa[x]==x?x:pa[x]=chazhao(pa[x]);
}
bool unite(long long x,long long y)
{
	x=chazhao(x),y=chazhao(y);
	if(x==y) return false;
	else{
		pa[x]=y;
		return true;
	}
}
long long kruskal()
{
	init();
	sort(E,E+to);
	long long result=0;
	long long cnt=0;
	for(long long i=0;i<to;i++)
	{
		if(unite(E[i].u,E[i].v))
		{
			result+=E[i].w;
			cnt++;
			if(cnt==n) return result;
		}
		
	}
	return -1;
}
int main()
{
	cin>>n;
	cin>>m;
   
	long long u,v;
	long long w;
    cin>>w;	
	for(int i=1;i<=n;i++)
	{

	    E[to].u=0,E[to].v=i,E[to].w=w,to++;
	    E[to].u=i,E[to].v=0,E[to].w=w,to++;
	}
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v>>w;
		E[to].u=u,E[to].v=v,E[to].w=w,to++;
		E[to].u=v,E[to].v=u,E[to].w=w,to++;
	}
	cout<<kruskal();
	return 0;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值