山东大学计算机科学与技术学院程序设计思维与实践作业
山大程序设计思维与实践作业
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;
}