POJ 1258 最小生成树模版———Kruskal算法

版权声明:低调地前行,越努力越幸运! https://blog.csdn.net/SSYITwin/article/details/82012773

输入图的邻接矩阵,求最小生成树的总权值(多组数据)

Input

The input includes several cases. For each case, the first line contains the number of farms, N (3 <= N <= 100). The following lines contain the N x N conectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem.

Output

For each case, output a single integer length that is the sum of the minimum length of fiber required to connect the entire set of farms.

Sample Input

4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0

Sample Output

28

1.Kruskal算法:

     将图G中的边按权值从小到大依次选取(排序函数——sort()),若选取的边使生成树不形成回路,则把它并入TE中,若形成回路则将其舍弃,直到TE中包含n-1条边为止,此时T为最小生成树。Kruskal算法就是加边,找最小权值的加入。

2.关键问题:如何判断欲加入的一条边是否与生成树中边构成回路?——并查集 

     将各顶点划分为所属集合的方法来解决,每个集合的表示一个无回路的子集。开始时边集为空,N个顶点分属N个集合,每个集合只有一个顶点,表示顶点之间互不连通。 

    当从边集中按顺序选取一条边时,若它的两个端点分属于不同的集合,则表明此边连通了两个不同的部分,因每个部分连通无回路,故连通后仍不会产生回路,此边保留,同时把相应两个集合合并

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring> 
#include<vector>
using namespace std;
struct Edges
{
	int i;
	int j;
	int w;
	bool operator<(const Edges &e)const
	{
		return w<e.w;
	}
	Edges(int ii,int jj,int ww):i(ii),j(jj),w(ww){}
	Edges(){}
};
vector<Edges>edges;
vector<int>par;
int getRoot(int root)
{
	if(par[root]!=root)
	    par[root]=getRoot(par[root]);
	return par[root];
}
void Merge(int x,int y)
{
	int fx=getRoot(x);
	int fy=getRoot(y);
	if(fx!=fy)
	{
		par[fy]=fx;
	}
}

int main()
{
	int n;
	while(cin>>n){
	par.clear();
	edges.clear();
	for(int i=0;i<n;i++)
	    par.push_back(i);
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			int w;
			scanf("%d",&w);
			edges.push_back(Edges(i,j,w));
		}
	}
	int ans=0;
	int cnt=0;
    sort(edges.begin(),edges.end());
    for(int k=0;k<edges.size();k++)
    {

    	if(getRoot(edges[k].i)!=getRoot(edges[k].j))
    	{
    		Merge(edges[k].i,edges[k].j);
    		cnt++;
    		ans=ans+edges[k].w;
		}
		if(cnt==n-1)  break;
		
	}
	cout<<ans<<endl;
    } 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SSYITwin/article/details/82012773