最小生成树算法我只知道两种:Prim和Kruscal。
Prim算法跟Dijkstra算法一样,属于典型的贪心算法(即从局部最优解得到全局最优解)。
下面是Prim算法用于以邻接矩阵保存的图的情况。
#define N 1000
int edge[N][N],closedge[N],n;
bool vis[N];
void prim(int s)
{
int i,j,k;
for(i=1;i<=n;i++)
closedge[i]=edge[s][i];
memset(vis,0,sizeof(vis));
vis[s]=true;
for(j=1;j<=n-1;j++)
{
k=1;
while(vis[k])k++;
int beg=k;
for(i=k+1;i<=n;i++)
if(!vis[i]&&closedge[i]<closedge[k])
k=i;
vis[k]=true;
for(i=beg;i<=n;i++)
if(!vis[i]&&edge[k][i]<closedge[i])
closedge[i]=edge[k][i];
}
}
下面是Prim算法用于以静态邻接表保存的图的情况。
#define N 1000
#define Inf 9999999
struct Edge
{
int to,w,next;
}e[100000];
int pp[N],n,closedge[N];
bool vis[N];
void prim(int s)
{
int i,j,k;
for(i=1;i<=n;i++)
closedge[i]=Inf;
closedge[s]=0;
memset(vis,0,sizeof(vis));
for(j=1;j<=n;j++)
{
k=1;
while(vis[k])k++;
for(i=k+1;i<=n;i++)
if(!vis[i]&&closedge[i]<closedge[k])
k=i;
vis[k]=true;
for(i=pp[k];i!=-1;i=e[i].next)
if(!vis[e[i].to]&&e[i].w<closedge[e[i].to])
closedge[e[i].to]=e[i].w;
}
}
同样的,Prim算法可以用优先队列来优化。
#define N 1000
#define Inf 9999999
struct Edge
{
int to,w,next;
}e[100000];
int ec,pp[N],closedge[N],n;
bool vis[N];
struct Node
{
int u,d;
bool operator<(const struct Node a)const
{
return d>a.d;
}
}t1;
void prim(int s)
{
int i,j,k;
priority_queue<struct Node>que;
for(i=1;i<=n;i++)
closedge[i]=Inf;
memset(vis,0,sizeof(vis));
closedge[s]=0;
t1.d=0;
t1.u=s;
que.push(t1);
while(!que.empty())
{
t1=que.top();
que.pop();
k=t1.u;
if(vis[k])continue;
vis[k]=true;
for(i=pp[k];i!=-1;i=e[i].next)
{
if(!vis[e[i].to]&&e[i].w<closedge[e[i].to])
{
closedge[e[i].to]=e[i].w;
t1.d=e[i].w;
t1.u=e[i].to;
que.push(t1);
}
}
}
}
Prim算法一般用于稠密图的情况,Kruscal算法则一般用于稀疏图的情况。在下面的Kruscal算法中还用到了并查集。
#define N 1000
struct Edge
{
int u,v,w;
}e[100000];
int parent[N],cnt,n;
int Find(int x)
{
if(parent[x]<0)
return x;
int r=Find(parent[x]);
parent[x]=r;
return r;
}
void Union(int x,int y)
{
int a=Find(x),b=Find(y);
if(a!=b)parent[a]=b;
}
int cmp(const void* a,const void* b)
{
return ((struct Edge*)a)->w-((struct Edge*)b)->w;
}
void kruscal()
{
int i,j,k=0;
memset(parent,-1,sizeof(parent));
qsort(e,cnt,sizeof(struct Edge),cmp);
for(i=0;i<cnt;i++)
if(Find(e[i].u)!=Find(e[i].v))
{
Union(e[i].u,e[i].v);
k++;
if(k==n-1)
break;
}
}

2779

被折叠的 条评论
为什么被折叠?



