吉林大学计算机23级数据结构上机实验(第八周)

A 快速排序

给定包含n个元素的整型数组a[1],a[2],...,a[n],利用快速排序算法对其进行递增排序,请输出排序过程,即每次Partition之后的数组。最后输出排序后的数组。每次选择所处理的子数组的第一个元素作为基准元素。

输入格式:

输入为两行,第一行为一个整数n(1<n≤1000),表示数组长度。第二行为n个空格间隔的整数,表示待排序的数组。

输出格式:

输出为若干行,每行依次输出Partition后的整个数组,每个元素后一个空格。最后一行输出排序后的数组。

输入样例:

5
4 5 3 2 1

输出样例:

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

提示:

就是在每次调用完Partition函数后输出R[1]....R[n]。其余与快速排序一致。
背一个快排模板。。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N];
int n;

void quicksort(int l, int r) {
    if (l >= r) {
        return;
    }
    int x = a[l]; 
    int i = l, j = r + 1;
    while (i < j) {
        do i++; while (i <= r && a[i] <= x); 
        do j--; while (a[j] > x);
        if (i < j) {
            swap(a[i], a[j]);
        }
    }
    swap(a[l], a[j]); 
    for (int i = 1; i <= n; i++) {
        cout << a[i] << " ";
    }cout << endl;
    quicksort(l, j - 1);
    quicksort(j + 1, r);
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    quicksort(1, n);
    for (int i = 1; i <= n; i++) {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

B 网络布线

亚洲杯赛期间需要保证运动员公寓网络畅通,以使运动员都能正常上网。

假定公寓楼内有n个房间,编号为0...n−1,每个房间都需要网络连接。房间 i 有网络,当且仅当满足如下2个条件之一:

(1)房间 i 安装了路由器(成本为 ri​>0)

(2)房间 i 和房间 j 有网线连接且房间 j 有网络(在房间 i 和房间 j 之间布置网线的成本为 fij​>0)

假定你是赛事组委会的网络工程师,请编写程序设计一个网络布线方案(哪些房间安装路由器,哪些房间之间布置网线),使得所有房间都有网络,且总成本最小。

例如下图包含7个房间和10个可能的连接,安装路由器的成本为括号内数字,房间之间布置网线的成本为边的权值。其解决方案为右下图,即在房间1和4安装路由器,并进行图中的网线布置。总成本为120。

输入格式:

输入第一行为两个正整数n和e;n为房间数,不超过600;e为可能的连接数,不超过2×105。接下来一行为n个空格间隔的正整数,第i个整数(i≥0)表示在房间i安装路由器的成本。接下来e行,每行为3个非负整数i、j、f,表示在房间i和房间j之间布置网线的成本为f。

输出格式:

输出为一个整数,表示最优网络布线方案的成本。

输入样例:

7 10
60 10 35 55 40 70 70
0 1 20
0 4 75
0 3 45
1 3 50
1 2 15
2 6 5
5 6 45
4 5 5
3 5 25
3 6 65

输出样例:

120

提示:

可引入一个虚拟顶点,将该顶点与其他所有顶点用边相连,边权等于那些顶点的权值。进而形成一个新图,对新图求最小支撑树。注意本题顶点编号从0开始。


超级源点的最小生成树。。

注意如果用cin输入时记得加开关。。不然会超时。如果不想加那么用scanf就好了。

这里给出kruskal和prim的两种做法。

kruskal:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int p[N];
int n, m;
int ans;
struct edge {
	int a, b, w;
	bool operator<(edge& W) {
		return w <W. w;
	}
}e[N];
int find(int x) {
	if (p[x] != x) {
		p[x] = find(p[x]);
	}
	return p[x];
}
void solve()
{
	cin >> n >> m;
	for (int i = 0;i <= n;i++) {
		p[i] = i;
	}
	int cnt = 0;
	for (int i = 1;i <= n;i++) {
		int k;
		cin >> k;
		cnt++;
		e[cnt].a = i - 1;
		e[cnt].b = n;
		e[cnt].w = k;
	}
	for (int i = 1;i <= m;i++) {
		int a, b, c;
		cin >> a >> b >> c;
		cnt++;
		e[cnt].a = a;
		e[cnt].b = b;
		e[cnt].w = c;
	}
	sort(e + 1, e + cnt+1);
	for (int i = 1;i <= cnt;i++) {
		//cout << e[i].w << endl;
		int x = find(e[i].a);
		int y = find(e[i].b);
		if (x != y) {
			ans += e[i].w;
			p[x] = y;
		}
	}
	cout << ans;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	solve();
	return 0;
}

prim:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=650,M = 3e5 + 10;
int h[N], e[M], w[M], ne[M], idx;
int dist[N], st[N];
int n, m;
int ans;

void add(int a, int b, int c)
{
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void prim()
{
	memset(st, 0, sizeof st);
	memset(dist, 0x3f, sizeof dist);
	dist[0] = 0;
	//cout << 1 << endl;
	for (int i = 0; i <= n; i++) {
		int t = -1;
		//cout << 1 << endl;
		for (int j = 0; j <= n; j++) {
			if (!st[j] && (t == -1 || dist[j] < dist[t])) {
				t = j;
			}
		}
		st[t] = 1;
		ans += dist[t];
		for (int j = h[t]; ~j; j = ne[j]) {
			int k = e[j];
			if (w[j] < dist[k]) {
				dist[k] = w[j];
			}
		}
	}
}

void solve()
{
	cin >> n >> m;
	memset(h, -1, sizeof h);
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		int k;
		cin >> k;
		add(n, i, k);
		add(i, n, k);
	}
	for (int i = 1; i <= m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
		add(b, a, c);
	}
	//cout << 1 << endl;
	prim();
	cout << ans;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	solve();
	return 0;
}

堆优化后的prim:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=650,M = 3e5 + 10;
int h[N], e[M], w[M], ne[M], idx;
int dist[N], st[N];
int n, m;
int ans;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
void add(int a, int b, int c)
{
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void prim()
{
	memset(st, 0, sizeof st);
	memset(dist, 0x3f, sizeof dist);
	q.push({ 0, 0 });
	dist[0] = 0;
	while (q.size())
	{
		auto t = q.top();
		q.pop();
		int ver = t.second, distance = t.first;
		if (st[ver]) {
			continue;
		}
		st[ver] = 1;
		ans += distance;
		for (int i = h[ver]; ~i; i = ne[i]) {
			int j = e[i];
			if (dist[j] > w[i]) {
				dist[j] = w[i];
				q.push({ dist[j], j });
			}
		}
	}
}

void solve()
{
	cin >> n >> m;
	memset(h, -1, sizeof h);
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		int k;
		cin >> k;
		add(n, i, k);
		add(i, n, k);
	}
	for (int i = 1; i <= m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
		add(b, a, c);
	}
	//cout << 1 << endl;
	prim();
	cout << ans;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	solve();
	return 0;
}

C 最大边

给定一个包含n个顶点的无向正权连通图,顶点编号为1到n。请编写程序计算其最小支撑树中任意两个顶点间路径中,权值最大的边的权值。

输入格式:

第一行为2个正整数n和m,n为图中顶点个数,m为边的条数。接下来m行,每行3个整数a、b、c,表示顶点a和顶点b之间有一条权值为c的边。随后一行为一个正整数T,表示查询数目。接下来T行,每行2个整数a和b,表示查询最小支撑树中顶点a和b间路径中的最大边。n≤2000,m≤30000,1 ≤a,b≤ n且a=b,c ≤65535,T ≤ 1000 。

输出格式:

对于每个查询输出一行,为1个整数,表示最小支撑树两个顶点间的路径中的最大边的权值。

输入样例:

8 20
2 7 44181
1 2 36877
3 6 2506
2 8 46829
7 1 2843
4 5 40699
1 3 15911
7 6 15553
5 6 22541
8 6 62008
3 4 62009
5 7 53337
5 3 12157
4 6 10112
1 5 22574
3 7 28993
4 7 53536
6 1 951
4 2 31411
7 8 31020
10
7 5
5 4
4 2
7 2
3 4
1 5
1 5
7 3
6 1
4 1

输出样例:

12157
12157
31411
31411
10112
12157
12157
2843
951
10112

这个题没有用标准的解法,暴力搞的,不过也能过,凑合看吧,懒得写其他的了。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10, M = 2010;
int h[M], e[N], ne[N], w[N], idx;
int p[N];
int cnt[M];
int n, m, t;

struct edge {
	int a, b, w;
	bool operator<(edge& W) {
		return w <W. w;
	}
}ed[N];

void add(int a, int b, int c) {
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
int find(int x) {
	if (p[x] != x) {
		p[x] = find(p[x]);
	}
	return p[x];
}
void bfs(int a, int b) {
	int res = 0;
	bool flag = 1;
	bool st[M];
	memset(st, false, sizeof st);
	memset(cnt, 0, sizeof cnt);
	queue<int >q;
	q.push(a);
	while (q.size()) {
		//cout << 1 << endl;
		int v = q.front();
		q.pop();
		if (st[v]) {
			continue;
		}
		st[v] = true;
		for (int i = h[v];~i;i = ne[i]) {
			int j = e[i];
			if (st[j]) {
				continue;
			}
			cnt[j] = max(cnt[v], w[i]);
			//cout << w[i] << endl;
			q.push(j);
		}
	}
}
void solve()
{
	cin >> n >> m;
	memset(h, -1, sizeof h);
	for (int i = 0;i <= n;i++) {
		p[i] = i;
	}
	for (int i = 1;i <= m;i++) {
		int a, b, c;
		cin >> a >> b >> c;
		ed[i].a = a;
		ed[i].b = b;
		ed[i].w = c;
	}
	sort(ed + 1, ed + m+1);
	for (int i = 1;i <= m;i++) {
		//cout << ed[i].w << endl;
		int x = find(ed[i].a);
		int y = find(ed[i].b);
		if (x != y) {
			p[x] = y;
			add(ed[i].a, ed[i].b, ed[i].w);
			add(ed[i].b, ed[i].a, ed[i].w);
		}
	}
	cin >> t;
	while (t--) {
		int a, b;
		cin >> a >> b;
		bfs(a, b);
		cout << cnt[b] << endl;
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	solve();
	return 0;
}
相关推荐
机器学习之心25 分钟前
一区正弦余弦算法!SCA-SVM正弦余弦算法优化支持向量机多特征分类预测
算法·支持向量机·分类·sca-svm·正弦余弦算法优化
a栋栋栋1 小时前
刷算法心得
算法
華華3551 小时前
读程序题...
开发语言·c++·算法
m0_547486661 小时前
西安交通大学2001年数据结构试题
数据结构
宸码2 小时前
【机器学习】手写数字识别的最优解:CNN+Softmax、Sigmoid与SVM的对比实战
人工智能·python·神经网络·算法·机器学习·支持向量机·cnn
太空漫步112 小时前
逆序对个数
java·算法·排序算法
23级二本计科2 小时前
分治_归并_归并排序(逆序对)
数据结构·算法·排序算法
CHENWENFEIc2 小时前
基础排序算法详解:冒泡排序、选择排序与插入排序
c语言·数据结构·算法·排序算法·学习方法·冒泡排序
养佳工具人2 小时前
Java各种排序
java·算法·排序算法
都适、隶仁ミ2 小时前
【密码学】SM4算法
linux·运维·服务器·算法·网络安全·密码学·网络攻击模型