zoj 1046(Jungle Roads)Kruskal 并查集实现

 
 
    关于最小生成树现在我只看了克鲁斯卡尔算法,prim算法还没来得及看,先练练kruskal吧,ta用的都是这两个方法写的,确实比较牛,我也正在努力超越,这道题就是纯粹的最小生成树,白书上说kruskal算法基本上都是和并查集一起用的,这样实现起来更高效,确实不错。

关于刷题,我似乎有点感触了,我觉得不能一味的刷题,用题目的数量来满足自己,其实学习一个知识点,我们要理解为什么要用到它,用它来干什么,它可以帮助我们解决什么样的问题,所以,以后学习算法就要多思考,多总结,不能简简单单为了AC,话说最近一直都是提交一次就过了诶,哈哈,继续练,加油

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct 
{
	int i,j;//用来存放节点两端的序号 
	int len;//len存放权值 
}node;
int p1[100];
node map[100];
int find(int x)
{
	return p1[x]==x? x:p1[x]=find(p1[x]);//用并查集实现判断连个节点是否在同一个连通分量里面,即判断是不是会构成一个环 
}
int cmp(const void *a,const void *b)
{
	return ((node *)a)->len-((node *)b)->len;//对结构体数组进行排序,放在一个结构体数组就可以实现由一个变量决定的序列 
}
int main()
{
	int n,i,j,k;
	char x;
	int p,q,z,y,ans,sum;
	while(scanf("%d",&n),n!=0)
	{
		sum=0;
		p1[1]=0;
		for(i=0;i<n;i++)
			p1[i]=i;//并查集的初始化 
		ans=0;
		for(i=0;i<n-1;i++)
		{
			getchar();
			scanf("%c",&x);
			p=x-'A';
			scanf("%d",&y);
			while(y--)
			{
				getchar();
				scanf("%c",&x);
				q=x-'A';
				scanf("%d",&z);
				map[ans].i=p;
				map[ans].j=q;
				map[ans++].len=z;
			}
		}
		qsort(map,ans,sizeof(map[0]),cmp);
		for(i=0;i<ans;i++)
		{
			int x1=find(map[i].i);//找到map[i].i的代表节点 
			int y1=find(map[i].j);//找到map[i].j的代表节点 
			if(x1!=y1)
			{
				sum+=map[i].len;
				p1[x1]=y1;//把他们放到同一个连通分量里面 
			}
		}
		printf("%d\n",sum);	
	}
}

又学习了Prim算法写了一遍,感觉很好哦,又学会了一种算法,又是一遍AC, 嘿嘿,是看ta的博客学习的,当然比较好过咯,接下来继续练习最小生成树kruskal算法和Prim算法奋斗

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
int map[30][30];
int n;
int visit[30];//visit数组用来标记该点是否已经被选过,
void prim()
{
	int dis[30],sum=0,min,i,j;//dis数组用来存放第i个点到已选择点集合的最短距离 
	for(i=1;i<=n;i++)
		dis[i]=INT_MAX;//初始化所以的点到被选中的点集合的最短距离为无穷大 
	dis[1]=0;visit[1]=1;//初始化第一个点,然后从第一个点逐渐找离所选集合点的最短距离 
    int now=1;
    for(j=1;j<=n;j++)
    {
	  for(i=1;i<=n;i++)
	  {
		if(!visit[i]&&dis[i]>map[now][i])//如果新加入的点到i的距离小于前面选过的点的距离,就更新 
			dis[i]=map[now][i];
      }	
	  int min=INT_MAX;
	  for(i=1;i<=n;i++)
	      if(!visit[i]&&dis[i]<min)//找到所选的点的集合离哪个未选的点距离最近,就把那个点加入该集合 
		    min=dis[now=i];
	  visit[now]=1;//标记该点已访问过		
    }
    for(i=1;i<=n;i++)
    	sum+=dis[i];
    printf("%d\n",sum);
}
int main()
{
	int i,j,k;
	char x;
	int p,q,z,y,ans,sum;
	while(scanf("%d",&n),n!=0)
	{
		memset(visit,0,sizeof(visit));
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				map[i][j]=INT_MAX;
		for(i=1;i<n;i++)
		{
			getchar();
			scanf("%c",&x);
			p=x-'A'+1;
			scanf("%d",&y);
			while(y--)
			{
				getchar();
				scanf("%c",&x);
				q=x-'A'+1;
				scanf("%d",&z);
				map[q][p]=map[p][q]=z;
			}
		}
		prim();
	}
	return 0;
}


你可能感兴趣的:(zoj 1046(Jungle Roads)Kruskal 并查集实现)