最小生成树(模板)

kruskal算法:
#include<iostream>
using namespace std;

struct edge
{
    int x,y,c;
};
edge elist[250010];

int n,m,i,j,ans,num,psum;

bool hash[250010],bk;

int zu[501],e[501];
int cmp(const void *s,const void *t)
{
    edge i=*(edge *)s,j=*(edge *)t;
    return i.c-j.c;
}
int find(int x)
{
    if (x!=zu[x]) zu[x]=find(zu[x]);
    return zu[x];
}
void kruskal()
{
    int i,a,b;
    for (i=1;i<=n;i++) zu[i]=i;
    num=0;
    for (i=1;i<=m;i++)
    {
        a=find(elist[i].x);
        b=find(elist[i].y);
        if (a!=b)
        {
            zu[b]=a;
            ans+=elist[i].c;
            num++;
            e[num]=i;
            if (num==n-1) 
				return;
        }
    }
}
void sec_kruskal()
{
    int nnum=0,a,b,i1;
    for (i1=1;i1<=n;i1++) zu[i1]=i1;
    for (i1=1;i1<=m;i1++)
      if (hash[i1])
      {
            a=find(elist[i1].x);
            b=find(elist[i1].y);
            if (a!=b)
            {
                psum+=elist[i1].c;
                zu[b]=a;
                nnum++;
                if (nnum==n-1)
                {
                    bk=true;
                    return;
                }
            }
        }
}
int main()
{
    scanf("%d%d",&n,&m);

    for (i=1;i<=m;i++)
      scanf("%d%d%d",&elist[i].x,&elist[i].y,&elist[i].c);

    qsort(elist+1,m,sizeof(edge),cmp);
    ans=0;
    kruskal();
    printf("Cost: %d\n",ans);
    ans=0x7fffffff;
    memset(hash,1,sizeof(hash));
    for (i=1;i<=num;i++){
        hash[e[i]]=0;
        psum=0;
        bk=false;
        sec_kruskal();
        if (bk)
        {
            if (psum<ans) ans=psum;
        }
        hash[e[i]]=1;
    }
    if (ans==0x7fffffff) 
		 printf("Cost: %d\n",-1);
    else 
		printf("Cost: %d\n",ans);
    return 0;
}

prim算法:
#include<iostream>
#include<cmath>
#define N 999999
double map[101][101];
int visited[101];
double mark[101];
int n;
using namespace std;
double dit (double x1,double y1,double x2, double y2)
{
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double prim()
{
	int i,j,k;
	double sum=0,min;
	memset(mark,0,sizeof(mark));
	memset(visited,0,sizeof(visited));
	k=1;
	visited[k]=1;
	for(i=2;i<=n;i++)
	{
		mark[i]=map[k][i];               //计算k到各顶点的距离
	}
	min=N;

	for(i=1;i<=n-1;i++)                  
	{
		for(j=1;j<=n;j++)
			if(mark[j]<min&&!visited[j])
			{
				min=mark[j];
				k=j;
			}

		visited[k]=1;

		for(j=1;j<=n;j++)
		{
			if(mark[j]>map[k][j]&&!visited[j])
				mark[j]=map[k][j];
		}
	
		sum+=min;
		min=N;
	}

	return sum;

}

int main()
{
	int i,j;
	double x[101],y[101];
	while(cin>>n)
	{
		for(i=1;i<=n;i++)
			cin>>x[i]>>y[i];

		memset(map,0,sizeof(map));

		for(i=1;i<=n-1;i++)
		{
			for(j=i+1;j<=n;j++)
			{
				map[i][j]=map[j][i]=dit(x[i],y[i],x[j],y[j]);
			}

		}
		printf("%.2lf\n",prim());

	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值