问题描述
求解连通图的最小生成树问题
输入格式
输入的第一行包含 N N N和 M M M两个整数。其中, N N N为连通图中点的数量, M M M为连通图中边的数量。所有点的编号从 0 0 0到 N − 1 N-1 N−1。随后有M行数据,一条边的数据占用一行,每行包含三个数据,依次为该边连接的两个顶点编号和该边的权重。始终至少有一种方法能产生最小生成树。
输出格式
输出最小生成树的权重之和。
输入样例
6 10
0 1 4
0 4 1
0 5 2
1 2 1
1 5 3
2 3 6
2 5 5
3 4 5
3 5 4
4 5 3
输出样例
11
解题思路
测试代码
普通
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int main(){
struct node{///定义邻接表中的节点
size_t id;
int weight;
node(size_t id,int weight):id(id),weight(weight){}
};
size_t number,road;
cin >> number >> road;
vector<vector<node> > adjacency(number);///建立邻接表
for(size_t i=0;i<road;i++){
size_t left,right;
int weight;
cin >> left >> right >> weight;
adjacency[left].push_back(node(right,weight));///向邻接表中放入边
adjacency[right].push_back(node(left,weight));///向邻接表中放入边
}
vector<bool> mark(number,false);///标记已经访问过的点
vector<int> table(number,INT_MAX);///记录出发点到各点的距离初始化为无穷大
table[0] = 0;///出发点到出发点距离为零
size_t next = 0;///初始化下一次访问的点为出发点
int weight = 0;///初始化到下一次访问的点的距离为零
do{
for(node temp:adjacency[next]){///枚举当前访问点有向连接的各点
if((!mark[temp.id])&&(temp.weight<table[temp.id])){
table[temp.id] = temp.weight;///通过该点到其它点距离是否可以更近
}
}
mark[next] = true;///标记该点已经访问过
weight = UINT_MAX;///初始化到下一次访问点的距离为无穷大
for(size_t i=0;i<number;i++){
if(!mark[i]&&table[i]<weight){///选取未访问过的、到该点最小距离的点
weight = table[i];///记录到该点的距离
next = i;///记录该点的标号
}
}
}while(weight<INT_MAX);///已经访问过该点所在连通图的所有点
size_t sum = 0;
for(size_t i=0;i<table.size();i++){
sum += table[i];
}
cout << sum << endl;
return 0;
}
优先队列优化
#include <bits/stdc++.h>
using namespace std;
void prim(const vector<vector<pair<int, int> > > &adj, int sta, vector<int> &tab){
vector<bool> mas(adj.size(), false);
tab.resize(adj.size(), INT_MAX);
tab[sta] = 0;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
que.push({tab[sta], sta});
while(!que.empty()){
pair<int, int> nex = que.top();
que.pop();
if(mas[nex.second]){
continue;
}
mas[nex.second] = true;
for(auto &edg: adj[nex.second]){
if(!mas[edg.second] && tab[edg.second]>edg.first){
tab[edg.second] = edg.first;
que.push({tab[edg.second], edg.second});
}
}
}
}
int main(){
int n, k;
cin >> n >> k;
vector<vector<pair<int, int> > > a(n);///建立邻接表
for(int i=0; i<k; i++){
int l, r, v;
cin >> l >> r >> v;
a[l].push_back({v, r});///向邻接表中放入边
a[r].push_back({v, l});///向邻接表中放入边
}
vector<int> t;
prim(a, 0, t);
copy(t.begin(), t.end(), ostream_iterator<int>(cout, " "));
cout << endl;
size_t s = 0;
for(int i: t){
s += i;
}
cout << s << endl;
return 0;
}