9 A 2 B 12 I 25 B 3 C 10 H 40 I 8 C 2 D 18 G 55 D 1 E 44 E 2 F 60 G 38 F 0 G 1 H 35 H 1 I 35 3 A 2 B 10 C 40 B 1 C 20 0
216 30
分析:有n个结点,求把n个结点连通的最小边数和
最小生成树问题,第一次写Kruskal算法,在这里介绍一下。
kruskal算法是每次把最小边加入集合,对边进行一个从小到大的排序,然后每次取最小边放入边集合中,并确定每次放入的边都有新结点加入已访问的结点集合。
代码如下:
第一次代码如下:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define INF 10000000
using namespace std;
struct node{
int u,v,w;
/* bool operator<(const node &p)const{
return w<p.w;
}*/
}edge[30];
int pre[30],n,sum;
int map[30][30];
bool cmp(node a,node b)
{
return a.w<b.w;
}
int find(int x)
{//查找根节点
int r=x;
while(r!=pre[r])
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void Merge(int x,int y,int w)
{//判断两个节点是否连通
int fx=find(x),fy=find(y);
if(fx!=fy)
{
pre[fx]=fy;
sum+=w;
}
}
void Kruskal()
{//MST
int i,j;
int count=0;
for(i=1;i<=n;i++)
pre[i]=i;
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(map[i][j]!=INF)
{
edge[count].u=i;
edge[count].v=j;
edge[count++].w=map[i][j];
}
}
}
sort(edge,edge+count,cmp);
for(i=0;i<count;i++)
Merge(edge[i].u,edge[i].v,edge[i].w);
}
int main()
{
int i,j;
char u,v;
int w,m;
while(scanf("%d%*c",&n),n)
{
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
map[i][j]=(i==j? 0:INF);
for(i=1;i<n;i++)
{
scanf("%c %d%*c",&u,&m);
while(m--)
{
scanf("%c %d%*c",&v,&w);
map[u-'A'+1][v-'A'+1]=map[v-'A'+1][u-'A'+1]=w;
}
}
sum=0;
Kruskal();
printf("%d\n",sum);
}
return 0;
}
优化代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
struct node{
int u,v,w;
}edge[105];
int pre[30];
int n,sum,Count;
bool cmp(node a,node b)
{
return a.w<b.w;
}
int find(int x)
{
int r=x;
while(r!=pre[r])
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void Kruskal()
{
int i,j,fx,fy;
sum=0;
sort(edge,edge+Count,cmp);
for(i=0;i<n;i++)
pre[i]=i;
for(i=0;i<Count;i++)
{
fx=find(edge[i].u);
fy=find(edge[i].v);
if(fx!=fy)
{
sum+=edge[i].w;
pre[fx]=fy;
}
}
}
int main()
{
int i,j;
int w,m;
char u,v;
while(scanf("%d%*c",&n),n)
{
Count=0;
for(i=1;i<n;i++)
{
scanf("%c %d%*c",&u,&m);
while(m--)
{
scanf("%c %d%*c",&v,&w);
edge[Count].u=u-'A';
edge[Count].v=v-'A';
edge[Count++].w=w;
}
}
Kruskal();
printf("%d\n",sum);
}
return 0;
}