mooyyu

G7 - MST-Prim

c++11 graph limits algorithm unordered_set numeric

template< class type >
class MST_Prim {
	const int n;
	unordered_set<int> vis;
	type dis[maxn+1];
public:
	const int INF = numeric_limits<type>::max()>>1u;
	int ar[maxn+1][maxn+1] {};
	explicit MST_Prim(const int n): n(n) {
		for (int i = 1; i <= n; i++) fill(ar[i]+1, ar[i]+n+1, INF);
		for (int i = 1; i <= n; i++) ar[i][i] = 0;
	}
	type solve() {
		unordered_set< int >().swap(vis);
		for (int i = 1; i <= n; i++) vis.insert(i);
		fill(dis+1, dis+n+1, INF);
		dis[*vis.begin()] = 0;
		for (int k = 0, cur; k < n; k++) {
			cur = *vis.begin();
			for (const auto i : vis) if (dis[i] < dis[cur]) cur = i;
			if (dis[cur] == INF) return INF;
			vis.erase(cur);
			for (const auto i : vis) dis[i] = min(dis[i], ar[cur][i]);
		}
		return accumulate(dis+1, dis+n+1, (type)0);
	}
};

Notes

  • 虽然思想和Dijkstra基本一致, 但负权边的存在无影响, 可以用等价转换(曲线救国)的思想考虑下
  • 易错点:
  • 存图时注意处理重边(邻接矩阵通病)
  • 算法思路:
    1. 邻接矩阵存图
    2. 集合vis(表示未加入mst的点集)包含所有点,个点到mst距离dis数组(初值为INF)
    3. dis[任意一个初始点] = 0
    4. 循环n次(第一次循环结束后dis表示个点到初始点的距离)
    5. 在集合vis中找到距离mst最近的点cur
    6. cur从集合vis中删除
    7. 对(连接mst集合与vis集合的边集)进行更新