SharedSchoolSpace/作业/数据结构-金健/C++/第六章作业/第六章作业1.cpp

94 lines
3.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 初步了解后发现实现获取最短的距离有三种方法:
* 1. 使用标准库的merge或者inplace_merge也就是归并排序
* 2. 使用标准库的priority_queue也就是优先级队列也就是堆
* 3. 使用标准库的multiset也就是允许重复元素的集合好像是用红黑树实现的
* 由于这里每次只需要获取最短的路径,因此优先级队列可能是比较好的选择。
* (但是空间复杂度可能会比较高,因为$n$个节点最多需要存$n^2$条边,而实际上
* 最小生成树只要n-1条边就可以全部连通优先级队列无法把长度过大的不可能选中的边排除
* 但是优先级队列每次好像只能一个一个加那还是用merge吧。
*/
/*
* 可以证明第二条规则无效,证明如下:
* 若A、B、C三个城市存在环即A申请修建ABB申请修建BCC申请修建CA那么根据每个城市
* 只会选择与它最近的城市修建公路则必定有AB < AC, BC < BA, CA < CB因此
* AB < AC < BC < AB而AB < AB是不可能的因此不会存在这样的情况
* 同理可以证明n个城市n > 2必定不存在环。
*/
/*
* 由于第二条规则无效在第一题中政府可以看做永远同意修建因此n个城市一轮后就会修建了
* n条公路而n-1条公路就能使城市全部连通因此一轮结束后城市就已全部连通。
*/
#include <iostream>
#include "graph.hpp"
// 一轮
void one_turn(Graph* graph) {
for (int start = 0; start < graph->node_num; ++start) {
int target;
while (true) {
int* target_ptr = std::min_element(graph->adjacency[start],
graph->adjacency[start] + graph->node_num);
// 如果最小的目标城市距离都是INT_MAX则说明start与所有城市都已连通则不再修建
if (*target_ptr == INT_MAX) {
return;
}
target = target_ptr - graph->adjacency[start];
// 如果在同一个城市联盟内,那么把这个目标城市排除,在剩下的目标城市中继续
if (graph->same_league(start, target)) {
graph->adjacency[start][target] = INT_MAX;
continue;
}
// 如果已经修建过了,则换个目标城市
if (graph->incidence[start][target]) {
continue;
}
// 不需要考虑三个或以上成环的情况
break;
}
// 修建公路即在关系矩阵上将相应的行列置为true
graph->incidence[start][target] = graph->incidence[target][start] = true;
// 把目标城市所在联盟合并到起始城市所在联盟中
graph->merge(start, target);
}
}
int main() {
int n;
std::cout << "输入城市的个数:";
std::cin >> n;
auto graph = Graph(n);
std::cout << "初始的距离的邻接矩阵为:" << std::endl;
graph.print_adjacency();
one_turn(&graph);
std::cout << "第一轮后的关系矩阵如下:" << std::endl;
graph.print_incidence();
std::cout << "并查集如下:" << std::endl;
graph.print_merge_find_set();
std::cout << "可以看到,一轮后就已经全部连通。" << std::endl;
return 0;
}
// 输入城市的个数5
// 初始的距离的邻接矩阵为:
// 2147483647 69 19 14 90
// 69 2147483647 66 82 66
// 19 66 2147483647 48 8
// 14 82 48 2147483647 22
// 90 66 8 22 2147483647
//
// 第一轮后的关系矩阵如下:
// 0 0 0 1 0
// 0 0 1 0 0
// 0 1 0 0 1
// 1 0 0 0 1
// 0 0 1 1 0
//
// 并查集如下:
// -1 0 0 0 0
// 可以看到,一轮后就已经全部连通。