hdu1102最小生成树的解--prim算法和kruscal算法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102

一;利用kruscal算法:

利用到了并查集的思想。getParent()利用是一种两趟方法(two-path method),一趟是沿查找路径上升,直到找到根,第二趟是沿路径下降,以便更新每个节点使之直接指向根。

另外按rank合并没有体现,其思想是为每个节点添加一个rank,好让合并的时候节点较少的节点直接指向节点较多的节点。

int N;
int len=0;
int parent[105];

struct Edge{
    int a,b,v;
}edges[5000];
int cmp(const Edge& lhs,const Edge& rhs){
    return lhs.v<rhs.v;
}
int getParent(int x){
    if(parent[x]!=x){
        parent[x]=getParent(parent[x]);
    }
    return parent[x];
}
void unon(int x,int y){
    int u=getParent(x);
    int v=getParent(y);
    if(u!=v){
        parent[u]=v;
    }
}
int kruscal(){
    int res=0;
    sort(edges+1,edges+len+1,cmp);
    for(int i=1;i<=N;++i){
        int u=getParent(edges[i].a);
        int v=getParent(edges[i].b);
        if(u!=v){
            res+=edges[i].v;
            unon(u,v);
        }
    }
    return res;
}

int main()
{

    freopen("in.txt","r",stdin);
    int n,i,j,tmp;
    while(scanf("%d",&N)!=EOF)
    {
        len=0;
        for(i=1;i<=N;i++)
            for(j=1;j<=N;j++){
                if(j>i){
                    edges[len].a=i;
                    edges[len].b=j;
                    cin>>edges[len].v;
                    len++;
                }else{
                    cin>>tmp;
                }
            }
        scanf("%d",&n);
        //初始化父亲数组
        for(int i=1;i<=N;++i){
            parent[i]=i;
        }
        while(n--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            unon(getParent(u),getParent(v));
        }
       cout<< kruscal()<<endl;
    }

   system("pause");
    return 0;
}

二,利用prim算法:从一点出发,依次寻找最短的,同时更新到已经连通区域的最短路径的长度(即未连通点到已加入连通集合点的最短边);

int Prim(){
	memset(vis,false,sizeof(vis));
	int res=0;
	for(int i=1;i<=N;++i){
		cost[i]=map[1][i];
	}
	vis[1]=true;
	for(int i=1;i<N;++i){
		int min=INT_MAX;
		int p=-1;
		for(int j=1;j<=N;++j){
			if(!vis[j]&&min>cost[j]){
				p=j;min=cost[j];
			}
		}
		if(min==INT_MAX) return -1;
		vis[p]=true;
		res+=min;
		for(int j=1;j<=N;++j){
			if(cost[j]>map[p][j]){
				cost[j]=map[p][j];
			}
		}
	}
	return res;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值