POJ1258 Agri-Net MST最小生成树题解

搭建一个最小代价的网络,最原始的最小生成树的应用。

这里使用Union find和Kruskal算法求解.

注意:

1 给出的数据是原始的矩阵图,但是需要转化为边表示的图,方便运用Kruskal,因为需要sort

2 减少边,一个矩阵最多需要(N*N-N)>>1条边,有人讨论本题是否有向,那是无意义的,因为本题的最小生成树和方向无关。

3 使用Union find是为了判断是否有环,比原始判断快很多。


#include <stdio.h>
#include <stdlib.h>

const int MAX_VEC = 101;
int N;	//number of vertices
struct SubSet
{
	int p, rank;
};

struct Edge
{
	int src, des, wei;
};

struct Graph
{
	int V, E;
	Edge *edge;
	Graph(int v, int e) : V(v), E(e)
	{
		edge = new Edge[E];
	}
	~Graph()
	{
		if (edge) delete[]edge; edge = NULL;
	}
};

static int cmp(const void *a, const void *b)
{
	Edge *a1 = (Edge *) a;
	Edge *b1 = (Edge *) b;
	return a1->wei - b1->wei;
}

SubSet *subs;
Edge *res;
Graph *gra;

void initResource()
{
	subs = new SubSet[N];
	for (int i = 0; i < N; i++)
	{
		subs[i].p = i;
		subs[i].rank = 0;
	}
	res = new Edge[N-1];
}

inline void releaseResource()
{
	if (subs) delete [] subs;
	if (res) delete [] res;
}

int find(int node)
{
	if (subs[node].p != node)
		subs[node].p = find(subs[node].p);
	return subs[node].p;
}

inline void unionTwo(int x, int y)
{
	int xroot = find(x);
	int yroot = find(y);
	if (subs[xroot].rank < subs[yroot].rank) subs[xroot].p = yroot;
	else if (subs[xroot].rank > subs[yroot].rank) subs[yroot].p = xroot;
	else
	{
		subs[xroot].rank++;
		subs[yroot].p = xroot;
	}
}

int mst()
{
	initResource();
	
	qsort(gra->edge, gra->E, sizeof(Edge), cmp);
	for (int i = 0, v = 0; i < gra->E && v < gra->V - 1; i++)
	{
		int xroot = find(gra->edge[i].src);
		int yroot = find(gra->edge[i].des);

		if (xroot != yroot)
		{
			unionTwo(xroot, yroot);
			res[v++] = gra->edge[i];
		}
	}

	int ans = 0;
	for (int i = 0; i < N-1; i++)
	{
		ans += res[i].wei;
	}
	releaseResource();
	return ans;
}

int main()
{
	int w;
	while (~scanf("%d", &N))
	{
		gra = new Graph(N, (N*N-N)>>1);
		int e = 0;
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				scanf("%d", &w);
				if (j <= i) continue;		//下三角形的值不入边

				gra->edge[e].src = i;
				gra->edge[e].des = j;
				gra->edge[e++].wei = w;
			}
		}
		printf("%d\n", mst());
		delete gra;
	}
	return 0;
}


POJ1258 Agri-Net MST最小生成树题解,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。