最小生成树问题

一:nyoj38http://acm.nyist.net/JudgeOnline/problem.php?pid=38

prim算法:

#include<cstdio>  
#include<cstdlib>  
#include<cstring>  
#define inf 0x3f3f3f3f  
using namespace std;  
int low[510],map[510][510],vis[510],v;//全局变量 
int prime(){  
        int min,pos,i,j,k,result=0;  
        memset(vis,0,sizeof(vis));  
        pos=1;vis[1]=1;  
        for(i=1;i<=v;++i){  
            if(i!=pos)low[i]=map[pos][i];  
        }  
        for(j=1;j<v;++j){  
            min=inf;  
            for(i=1;i<=v;++i){  
                if(!vis[i]&&min>low[i]){  
                    min=low[i];pos=i;  
                }  
            }
			//printf("%d\n",min);  
            result+=min;vis[pos]=1;  
            for(i=1;i<=v;++i){  
                if(!vis[i]&&low[i]>map[pos][i])  
                    low[i]=map[pos][i];  
            }  
        }  
        return result;  
}  
int main()  
{  
    int n,k,i,j,a,b,min,e,c;  
    scanf("%d",&k);  
    while(k--){  
        memset(map,0x3f,sizeof(map));//初始化为int数据的最大值  
        scanf("%d%d",&v,&e);  
        while(e--){  
            scanf("%d%d%d",&a,&b,&c);  
            map[a][b]=map[b][a]=c;  
        }  
        min=inf;//无穷  
        for(i=0;i<v;++i){  
            scanf("%d",&a);  
            if(a<min)min=a;  
        }  
        min=min+prime();  
        printf("%d\n",min);  
    }  
    return 0;  
}  
kruskal算法:

#include<stdio.h>
#include<algorithm>
using namespace std;
struct stu
{
	int s;
	int u;
	int w;
}vt[130000];
int per[510];
int cross[510];
int cmp1(stu a,stu b)
{
	return a.w<b.w;
}
int cmp2(int a,int b)
{
	return a<b;
}
int find(int x)
{
	return x==per[x]?x:per[x]=find(per[x]);
}
bool join(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	{
		per[fx]=fy;
		return true;
	}
	else return false;
}
int main()
{
	int t,i,v,e;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&v,&e);
		for(i=0;i<e;i++)
			scanf("%d%d%d",&vt[i].s,&vt[i].u,&vt[i].w);
			  for(i=0;i<v;i++)
			  {
			  scanf("%d",&cross[i]);
			  per[i]=i;
		      }
		      per[i]=i;
		      int sum=0;
		      int flag=0;
		      sort(vt,vt+e,cmp1);
		      for(i=0;i<e;i++)
		      {
		      	if(join(vt[i].s,vt[i].u))
		      	{
		      		flag++;
		      		sum+=vt[i].w;
		      	}
		      	if(flag==v-1)break;
		      }
		      sort(cross,cross+v,cmp2);
			  sum+=cross[0];
			  printf("%d\n",sum);
	}
	return 0;
}

参考博客:http://blog.csdn.net/mblhq/article/details/47446869



二:hdu:1233http://acm.hdu.edu.cn/viewcode.php?rid=21723629

prime算法:

#include<iostream>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
int map[110][110],vis[110],low[110],v;
int prime()
{
   int min,pos,ans=0;
   memset(vis,0,sizeof(vis));
   pos=1;vis[1]=1;
   for(int i=1;i<=v;i++)
   if(!vis[i])
   low[i]=map[pos][i];
   for(int j=1;j<v;j++)
   {
   	min=inf;
   	for(int i=1;i<=v;i++)
   	if(!vis[i]&&min>low[i]){
   	min=low[i];pos=i;
   }
   ans+=min;vis[pos]=1;
   for(int i=1;i<=v;i++)
   {
   	if(!vis[i]&&low[i]>map[pos][i])
   	low[i]=map[pos][i];
   }
	   }
	   return ans;
	   	
}
int main()
{
	int a,b,c,t;
    while(cin>>v)
	{
		if(v==0)
		break;
		memset(map,0,sizeof(map));
		t=v*(v-1)/2;
		for(int i=0;i<t;i++)
		{
		   cin>>a>>b>>c;
		   map[a][b]=map[b][a]=c;
		}
		cout<<prime()<<endl;
	 } 
 } 

kruskal算法:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=10005;
struct node { int from,to,len;} edge[maxn];//储存边的数据结构
int n,fa[maxn],m,ans,q;
bool cmp(node a,node b) { return a.len<b.len; }//边按从小到大的顺序排列
int Find(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=Find(fa[x]);
}
void Merge(int x,int y)
{
    x=Find(x),y=Find(y);
    if(x!=y) fa[y]=x;
}
int kruskal()
{
    sort(edge,edge+m,cmp);//边排序
    for(int i=0;i<=n;i++) fa[i]=i;//初始化并查集
    ans=0;
    for(int i=0;i<m;i++)//一条边的两个端点不在同一个集合,则选它,并合并端点
        if(Find(edge[i].from)!=Find(edge[i].to)) Merge(edge[i].from,edge[i].to),ans+=edge[i].len;
    return ans;
}
int main()
{
    while(cin>>n,n)
    {
        m=n*(n-1)/2;
        for(int i=0;i<m;i++) cin>>edge[i].from>>edge[i].to>>edge[i].len;
        cout<<kruskal()<<endl;
    }
    return 0;
}

还有一种并查集+快排       来源:http://www.2cto.com/kf/201308/234398.html


#include"algorithm"
#include<stdio.h>
using namespace std;

struct node
{
int x,y,z;
}a[10000];


int cmp(node a,node b)
{
return a.z<b.z;
}


int pre[100000];
int find(int k)
{
if(k==pre[k])
return k;
pre[k]=find(pre[k]);
return pre[k];
}


int main()
{
int m,i,ans,f1,f2,n;
while(scanf("%d",&n),n)
{
for(i=1;i<=n;i++)
pre[i]=i;
m=(n-1)*n/2;
for(i=0;i<m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
sort(a,a+m,cmp);
ans=0;
for(i=0;i<m;i++)
{
f1=find(a[i].x);
f2=find(a[i].y);
if(f1!=f2)
{
pre[f1]=f2;
ans+=a[i].z;
}
}
printf("%d\n",ans);
}
return 0;
}



最小生成树的参考博客:http://www.cnblogs.com/xl1027515989/p/3597091.html

kruskal(克鲁斯卡尔)算法和prim(普里姆)算法参考博客:http://blog.csdn.net/weinierbian/article/details/8059129/

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html

http://www.2cto.com/kf/201603/496259.html



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值