USACO Guide银组3. 自定义比较器和坐标压缩

目录

例题1-Wormhole Sort

思路

代码实现

比较函数

方法1

方法2


例题1-Wormhole Sort

传送门

农夫约翰的奶牛已经厌倦了他每天早上离开谷仓前要自己分类的要求。他们刚刚完成了量子物理学博士学位,并准备加快速度。
今天早上,像往常一样,Farmer John 的 N 头奶牛 (1≤N≤105),方便地编号为 1…N,分散在整个谷仓的 N 个不同位置,也编号为 1…N,因此奶牛 i 位于位置 pi。但是今天早上还有M个虫洞(1≤M≤105),编号为1…M,其中虫洞i双向连接位置ai和位置bi,宽度wi(1≤ai,bi≤N,ai≠bi, 1≤wi≤109)。

在任何时间点,位于虫洞两端的两只奶牛可能会选择同时通过虫洞交换位置。奶牛必须执行这种交换,直到奶牛 i 在位置 i 1≤i≤N。

奶牛并不急于被虫洞压扁。帮助他们最大化他们必须用来分类自己的最窄虫洞的宽度。保证奶牛可以自行分类。

思路

题目的大致意思就是要将数列排序,以非下降序列用权制排序。例如:

1 2 9
1 3 7
2 3 10
2 4 3

排序完后:

2 4 3
1 3 7
1 2 9
2 3 10

代码实现

C++代码中,使用vector和pair是最简单的方法。

vector<pair<int,pair<int,int>>> v; 

vector其中有两对nested pairs

部分代码如下:

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

#define f first
#define s second

int main() {
	int M = 4;
	vector<pair<int,pair<int,int>>> v;
	for (int i = 0; i < M; ++i) {
		int a,b,w; cin >> a >> b >> w;
		v.push_back({w,{a,b}});
	}
	sort(begin(v),end(v));
	for (auto e: v) cout << e.s.f << " " << e.s.s << " " << e.f << "\n";
}

或者使用vector套array:

int main() {
	int M = 4;
	vector<array<int,3>> v; // or vector<vector<int>>
	for (int i = 0; i < M; ++i) {
		int a,b,w; cin >> a >> b >> w;
		v.push_back({w,a,b});
	}
	sort(begin(v),end(v));
	for (auto e: v) cout << e[1] << " " << e[2] << " " << e[0] << "\n";
}

比较函数

比较器所做的是比较两个对象,如下所示,基于我们的比较标准:

  • 如果对象 x 小于对象 y,则返回 true
  • 如果对象 x 大于或等于对象 y,则返回 false

方法1

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

struct Edge {
	int a,b,w;
	bool operator<(const Edge& y) { return w < y.w; }
};

int main() {
	int M = 4;
	vector<Edge> v;
	for (int i = 0; i < M; ++i) {
		int a,b,w; cin >> a >> b >> w;
		v.push_back({a,b,w});
	}
	sort(begin(v),end(v));
	for (Edge e: v) cout << e.a << " " << e.b << " " << e.w << "\n";
}

方法2

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

struct Edge {
	int a,b,w;
};

bool cmp(const Edge& x, const Edge& y) { return x.w < y.w; }

int main() {
	int M = 4;
	vector<Edge> v;
	for (int i = 0; i < M; ++i) {
		int a,b,w; cin >> a >> b >> w;
		v.push_back({a,b,w});
	}
	sort(begin(v),end(v),cmp);
	for (Edge e: v) cout << e.a << " " << e.b << " " << e.w << "\n";
}

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值