数据结构图 —— 编程作业 07 :公路村村通
Posted 大彤小忆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构图 —— 编程作业 07 :公路村村通相关的知识,希望对你有一定的参考价值。
题目描述: 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式: 输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N)。
随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。
为简单起见,城镇从1到N编号。
输出格式: 输出村村通需要的最低成本。
如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。
输入样例:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例:
12
代码实现:
- 方法1:Kruskal算法
#include<iostream>
using namespace std;
#include<queue>
#include<vector>
#define MaxVertex 1005
typedef int Vertex;
int N; // 顶点
int M; // 边
int parent[MaxVertex]; // 并查集
struct Node {
Vertex v1;
Vertex v2;
int weight;
// 重载运算符
bool operator < (const Node &a) const
{
return weight > a.weight;
}
};
priority_queue<Node> q; // 最小堆
vector<Node> MST; // 最小生成树
int sum;
// 初始化图信息
void BuildGraph()
{
Vertex v1, v2;
int w;
cin >> N >> M;
for (int i = 1; i <= N; i++)
{
parent[i] = -1;
}
// 初始化点
for (int i = 0; i < M; i++)
{
cin >> v1 >> v2 >> w;
struct Node tmpE;
tmpE.v1 = v1;
tmpE.v2 = v2;
tmpE.weight = w;
q.push(tmpE);
}
sum = 0;
}
// 路径压缩查找
int Find(int x)
{
if (parent[x] < 0)
return x;
else
return parent[x] = Find(parent[x]);
}
// 按秩归并
void Union(int x1, int x2)
{
x1 = Find(x1);
x2 = Find(x2);
if (parent[x1] < parent[x2])
{
parent[x1] += parent[x2];
parent[x2] = x1;
}
else
{
parent[x2] += parent[x1];
parent[x1] = x2;
}
}
void Kruskal()
{
while (MST.size() != M - 1 && !q.empty())
{
Node E = q.top(); // 最小堆,出队权重最小的
q.pop();
if (Find(E.v1) != Find(E.v2)) // 判断是否属于同一集合
{
sum += E.weight;
Union(E.v1, E.v2); // 并
MST.push_back(E);
}
}
}
int main()
{
BuildGraph();
Kruskal();
// 图连通
if (MST.size() == N - 1)
cout << sum << endl;
else
cout << -1 << endl;
system("pause");
return 0;
}
测试: 输入样例的测试效果如下图所示。
- 方法2:Prim算法
#include<iostream>
using namespace std;
#include<vector>
#define Inf 100000
#define MaxSize 1001
int G[MaxSize][MaxSize];
int parent[MaxSize];
int dist[MaxSize];
int N; // 顶点
int M; // 边
int sum;
vector<int>MST;
void BuildGraph()
{
int v1, v2;
int w;
cin >> N >> M;
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
G[i][j] = 0;
}
dist[i] = Inf;
parent[i] = -1;
}
for (int i = 0; i < M; i++)
{
cin >> v1 >> v2 >> w;
G[v1][v2] = w;
G[v2][v1] = w;
}
}
void Init(int x) //初始化第一个点和到周围点的距离
{
dist[x] = 0;
MST.push_back(x);
for (int i = 1; i <= N; i++)
{
if (G[x][i])
{
dist[i] = G[x][i];
parent[i] = x;
}
}
}
int FindMin() //找点周围路径最短的点
{
int min = Inf;
int xb = -1;
for (int i = 1; i <= N; i++)
{
if (dist[i] && dist[i] < min)
{
min = dist[i];
xb = i;
}
}
return xb;
}
void Prim(int s)
{
Init(s);
while (1)
{
int v = FindMin();
if (v == -1) //不存在这样的点
break;
sum += dist[v];
dist[v] = 0;
MST.push_back(v);
for (int i = 1; i <= N; i++)
{
if (G[v][i] && G[v][i] < dist[i])
{
dist[i] = G[v][i];
parent[i] = v;
}
}
}
}
int main()
{
BuildGraph();
Prim(1);
if (MST.size() == N)
cout << sum << endl;
else
cout << -1 << endl;
system("pause");
return 0;
}
测试: 输入样例的测试效果如下图所示。
以上是关于数据结构图 —— 编程作业 07 :公路村村通的主要内容,如果未能解决你的问题,请参考以下文章