两种算法kruskal&Prim
这两种算法都是求最小生成树的贪心算法,但是出发角度不一样。kruskal算法是从边出发,将边按权值从小到大排序,然后遍历选边;Prim算法是从顶点的角度出发,在V-U中找离U最近的顶点。这就决定了这两种算法的适用范围,kruskal适用于点多边少的情况,适用于稀疏图;Prim算法适用于边多点少的情况,适用于稠密图。
一点想法
刚开始是在集合论图论中学的两种算法,当时还觉得不好用程序实现,直到后来在算法课上讲,懂了之后确实有一种恍然大悟的感觉。通过对畅通工程系列的整理和总结,我发现对于算法的理解是非常非常重要的,一旦你明白了这个算法的原理,就会很容易明白它的实现过程,或者说很容易用程序把它实现。
kruskal&Prim板子题
HDU1863-kruskal
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=105;
struct road
{
int b;//起点
int e;//终点
int v;//成本
} a[maxn*maxn/2];
int root[maxn];
int n,m;//道路数,村庄数
int ans;//最低成本
int cnt;//要修建的道路数目
void init()
{
for(int i=0; i<maxn; ++i)
root[i]=i;
ans=0;
cnt=0;
}
bool sort1(road r1,road r2)//按照成本从低到高排序
{
return r1.v<r2.v;
}
int find_(int x)
{
if(x==root[x])
return x;
else
{
root[x]=find_(root[x]);
return root[x];
}
}
void kruskal()
{
init();
sort(a+1,a+n+1,sort1);
for(int i=1; i<=n; ++i)
{
int fb,fe;//记录两顶点的根结点
fb=find_(a[i].b);
fe=find_(a[i].e);
if(fb!=fe)
{
if(fb<fe)
root[fe]=fb;
else
root[fb]=fe;
ans+=a[i].v;
cnt++;
if(cnt==m-1)
break;
}
}
}
int main()
{
while(cin>>n>>m&&n)
{
int i;
for(i=1; i<=n; ++i)
cin>>a[i].b>>a[i].e>>a[i].v;
kruskal();
if(cnt==m-1)
cout<<ans<<endl;
else
cout<<"?"<<endl;
}
return 0;
}
HDU1233-Prim
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=105;
const int INF=1<<29;
int n,m;//顶点数,边数
int closest[maxn];//V-U中离U最近的顶点
int lowcost[maxn];//V-U中顶点到U的最小边权值
int vis[maxn];//是否在U中
int map_[maxn][maxn];
int ans;//最低成本
void init()
{
for(int i=1; i<=n; ++i)
{
closest[i]=1;
lowcost[i]=map_[i][1];
}
memset(vis,0,sizeof(vis));
ans=0;
vis[1]=1;
lowcost[1]=0;
}
void Prim()
{
init();
int i,j,k,min_num;
for(i=1; i<=n; ++i)
{
min_num=INF;
k=0;
for(j=1; j<=n; ++j)//找到V-U中离U最近的顶点
if(!vis[j]&&lowcost[j]<min_num)
{
k=j;
min_num=lowcost[j];
}
if(k==0)//V-U为空说明算法结束
break;
vis[k]=1;
for(j=1; j<=n; ++j)//更新lowcost[]和closest[]
if(!vis[j]&&map_[j][k]<lowcost[j])
{
lowcost[j]=map_[j][k];
closest[j]=k;
}
}
}
int main()
{
int i,j,a,b,v;
while(scanf("%d",&n)==1&&n)
{
m=n*(n-1)/2;
memset(map_,0,sizeof(map_));
for(i=0; i<m; ++i)
{
scanf("%d%d%d",&a,&b,&v);
map_[a][b]=v;
map_[b][a]=v;
}
Prim();
for(i=1; i<=n; ++i)
ans+=lowcost[i];
printf("%d\n",ans);
}
return 0;
}