【图论】最小生成树

最小生成树概念:

  给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一颗树,那么这棵树就称为生成树。如果边上有权值,那么使得边权和最小的生成树就叫做最小生成树(MST)。

常用算法:Prim 算法, Kruskal算法

Prim 算法

  Prim算法与Dijkstra算法十分相似,基于贪心思想。

模板:

const int INF = 0x3f3f3f3f;
int cost[MAX_V][MAX_V];
int mincost[MAX_V];
bool used[MAX_V];
int V;

int prim(){
	for(int i = 0; i < V; ++i){
		mincost[i] = INF;
		used[i] = false;
	}
	mincost[0] = 0;
	used[0] = true;
	int res = 0;
	for(int i = 1; i < V; ++i){
		int v = -1;
		for(int j = 0; j < V; ++j){
			if(!used[j] && (v == -1 || mincost[j] < mincost[v]))
				v = j;
		}
		if(v == -1) return -1; // 图不连通
		used[v] = true;
		res += mincost[v];
		for(int j = 0; j < V; ++j){
			if(!used[j] && mincost[j] > cost[v][j])
				mincost[j] = cost[v][j];
		}
	}
	return res;
}

 

Kruskal 算法

模板:

const int INF = 0x3f3f3f3f;
struct Edge{
	int u, v, cost;
};
bool comp(const Edge& e1, const Edge& e2){
	return e1.cost < e2.cost;
}
Edge edge[MAX_E];
int f[MAX_V];// 并查集
int V, E;

int Find(int x){
	if(f[x] == - 1)
		return x;
	return f[x] = Find(f[x]);
}
int kruskal(){
	for(int i = 0; i < MAX_V; ++i){
		f[i] = -1;
	}
	sort(edge, edge + E, comp);
	int res = 0, cnt = 0; 
	for(int i = 0; i < E; ++i){
		Edge e = es[i];
		int t1 = Find(e.u);
		int t2 = Find(e,v);
		if(t1 != t2){
			res += e.cost;
			f[t1] = t2;
			++cnt;
		}
		if(cnt == n - 1) break;
	}
	if(cnt < n - 1) return -1; // 不连通
	else return res;
}

  

 

posted @ 2018-03-26 12:17  Vincent丶丶  阅读(223)  评论(0编辑  收藏  举报