最小生成树

最小生成树(n个结点的连通图最小权重)

1.Prim算法(对点的选取加入)

用二维数组记录点和权值。先选取一个点作起始点,然后任选一个邻近未访问过的权值最小点,重复直到选出n个点。

#define INF 0x7FFFFFFF
int w[510][510];
int v[510],low[510];
//low[i]记录当前在S内, 未访问点到点i的最小距离
int main()
{
	int t,n,maxx,sum;
	bool first = true;
    cin >> t;
	while(t--) 
	{
		cin>>n;
		sum = maxx = 0;
		memset(v,0,sizeof(v));
		for(int i=1;i<=n;i++)
		  for(int j=1;j<=n;j++)  
cin>>w[i][j];  //邻接矩阵  

         v[1] = 1; //从点1开始,初始化设离点i最近的点是点1
		for(int i=2;i<=n;i++) low[i] = w[1][i];	

		for(int i=1;i<n;i++)
		{
			int x=1, m=INF; 
			for(int j=1;j<=n;j++)//找出未访问的最小low[j]点x
			  if(!v[j]&&low[j]<m){
			  	  x = j;
			  	  m = low[j];
			  }

			v[x] = 1;
			sum += m;
			if(maxx<m) maxx = m;
			for(int j=2;j<=n;j++){ //更新未访问点到点i的最短边
			  if(!v[j]&&low[j]>w[x][j])
				low[j] = w[x][j]; 
			} 
		}
		if(first) first=false;
		else cout<<endl;
		cout << maxx << " "<< sum<<endl;
	}  //sum为最小生成树总长度,maxx为其中的最长边 
    return 0;
}  


2.kruskal算法(对边的选择)

将所有边按权值从小到大排序,从权值最小边开始遍历每条边,直至图中所有节点都在同一个连通分量中

#define N 510
int father [N];
struct point{
    int x,y,len;
}pot[N*N];
int cmp(point x,point y){
    return x.len<y.len;
}
int find(int x){  //使用并查集
    while(x!= father [x])
      x= father [x];
    return x;
}
int main()
{
	int t,n,maxx,sum,a,b;
    cin >> t;
	while(t--)
 {
		cin>>n;
		sum = maxx = 0;
		int q = 0;
		for(int i=1;i<=n;i++)
		  for(int j=1;j<=n;j++){
		  	 cin>>pot[q].len;
		  	 pot[q].x = i;
		  	 pot[q++].y = j;
		  }  
       sort(pot,pot+q,cmp);
       for(int i=1;i<=n;i++) father[i]=i;      
       for(int i=0;i<q;i++) //遍历选边
       {
           a = find(pot[i].x);
           b = find(pot[i].y);
           if(a!=b){  //不连接成环就加入此边 
               sum += pot[i].len;
             if(pot[i].len>maxx)
                maxx=pot[i].len;
             father [b]=a; 
           }
        }	
		cout <<sum<<" "<< maxx <<endl;
	}  
    return 0;
}  



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值