NYOJ 38(最小生成树)

简介: 原来是求二维数组的每行或者每列的最小值,不过需要主要的是如果是4个点,只需要3条边就可以完全连接起来了,所以只需要找3次就行了。4条边有一条边会重复,需要舍弃。 就用题目的测试数据比较,用二维数组保存点与点连接的距离。

原来是求二维数组的每行或者每列的最小值,不过需要主要的是如果是4个点,只需要3条边就可以完全连接起来了,所以只需要找3次就行了。4条边有一条边会重复,需要舍弃。

就用题目的测试数据比较,用二维数组保存点与点连接的距离。

 


就用i代表行,j代表列。会发现 i,j都是从第二行开始的。而且跟y=x 直线对称。为什么说只要找到每行或者每列的最小值就行了呢。假设最开始没有2这个点,此时1,3,4就是一个集合。然后新添加一个点2进去,此时的最短路径就是点2到这个集合的最短路径,然后看2能够跟集合里面的哪些点连接,测试数据表示能看出来跟1,3,4都连接,所以找出与1,3,4连接的最小值就行,就能够构成一个新的最小生成树。然后比较过一个就标记下,不再重复找,接下来代码就简单了。

//因为每个楼都在最小生成树中,因此无论从哪号楼拉线都没有区别,所以只要选最小那个值就行
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define inf 0x7FFFFFFF/*就是INT_MAX,四个字节,共32位,而每四位为一个十六进制为,因为存在计算机中为补码,所以最高四位是0111,即7*/
int map[501][501];//**二维数组标记地图**//
bool a[501];
int cmp(const void *a,const void *b)
{
	return *(int *)a-*(int *)b;
}
int main()
{
	int T,m,n;int i,j,k;int min,t,x,y,value,ans;int b[501];//**用一维数组a[i]用来标记第i个点是否被访问过**//
	scanf("%d",&T);
	while(T--)
	{
		memset(b,0,sizeof(b));
		scanf("%d %d",&m,&n);
		ans=0;
		for(i=1;i<=m;i++)
			for(j=1;j<=m;j++)
				map[i][i]=inf;
		for(i=1;i<=n;i++)
		{
			scanf("%d %d %d",&x,&y,&value);
			map[x][y]=map[y][x]=value;//**把能够连接的线都用二维数组保存,并将二维数组赋值**//
		}
		for(i=0;i<m;i++)
			scanf("%d",&b[i]);//**无论从哪号楼拉线都没有区别,所以只要选最小那个值就行**//
		qsort(b,m,sizeof(int),cmp);
		for(i=2;i<=m;i++)
			a[i]=false;
		a[1]=true;//**访问过了,标记true,表示不再访问**//
		for(i=2;i<=m;i++)//**标记了就知道,i,j都是从2开始,并对称**//
		{
			min=inf;
			for(j=2;j<=m;j++)
			{
				if(min>map[i][j]&&!(a[j]==true&&a[i]==true))//**找出最小权值,避免环路**//
				{
					min=map[i][j];
					k=j;
				}
			}
		//	for(j=2;j<=m;j++)//**为下一次循环做准备,重新初始化**//
			//	a[j]=false;
		    a[k]=true;
			if(min!=inf)
				ans=ans+min;//**加上权值**//
			//printf("%d\n",ans);
		}
		printf("%d\n",ans+b[0]);
		system("pause");
	}
	return 0;
}        

  

 

目录
相关文章
|
3月前
|
算法
最短路之Floyd算法
最短路之Floyd算法
32 1
|
5月前
|
算法
Floyd算法的应用
Floyd算法的应用
32 0
|
4月前
|
算法
floyd算法
floyd算法
|
4月前
|
C++
|
4月前
|
机器学习/深度学习 编解码 算法
|
机器学习/深度学习 算法
floyd算法的实现
floyd算法的实现
|
算法
Floyd算法(多源最短路径问题)
Floyd算法(多源最短路径问题)
96 0
Floyd算法(多源最短路径问题)
|
机器学习/深度学习 定位技术