最小生成树

1.kruskal(克鲁斯卡尔)算法

将所有边由小到大排序,依次进行有效的扩展(即有一节点加入集合),直到已经形成一棵树,此时生成的树即为最小生成树
ps:需用并查集才更好

```

//洛谷1546
#include<cstdio>
#include<algorithm>
using namespace std;
int n,cnt,sum,ans;
int fa[105];

struct edg{
    int from,to,dis;
}edge[10005];

bool cmp(edg x,edg y){
    return x.dis<y.dis;
}

int find(int x)                                                                                                         //查找根节点
{ 
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}

void join(int a,int b){
    int x=find(a);
    int y=find(b);
    if(x!=y) fa[x]=y;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            int x;
            scanf("%d",&x);
            if(i!=j){
                cnt++;
                edge[cnt].dis=x;
                edge[cnt].from=i,edge[cnt].to=j;
            }
        }
    for(int i=1;i<=n;i++) fa[i]=i;
    sort(edge+1,edge+cnt+1,cmp);
    for(int i=1;i<=cnt;i++){
        if(find(edge[i].from)!=find(edge[i].to)){
            join(edge[i].from,edge[i].to);
            sum+=edge[i].dis;
            ans++;
        }
        if(ans==n-1) break;
    }
    printf("%d",sum);
    return 0;
}
```

2.prim(普里姆)算法

每次选一个 与最小生成树相连的最小花费最少的节点 进入最小生成树,并用这个节点尝试更新它所连所有节点的 与最小生成树相连的最小花费(因为有节点进入,最小生成树发生改变),直到最终完成

```

//洛谷1265
#include<cstdio>
#include<cmath>
using namespace std;
int n,cnt;
double sum;
int mst[5005];
double dis[5005][5005],mincost[5005];

struct point{
    int x,y;
}city[5005];

double qdis(int a,int b){
//  if(dis[a][b]) return dis[a][b];
//  else 
//  return dis[a][b]=dis[b][a]=sqrt(abs(city[a].x-city[b].x)*abs(city[a].x-city[b].x)+abs(city[a].y-city[b].y)*abs(city[a].y-city[b].y));
    return sqrt(abs(city[a].x-city[b].x)*abs(city[a].x-city[b].x)+abs(city[a].y-city[b].y)*abs(city[a].y-city[b].y));
}

void prim(int t){//函数没写好 懒得改了 明白怎么回事就好
    if(cnt==n-1) return ;
    cnt++;
    int k; double minn=0x3f3f3f3f;
    for(register int i=1;i<=n;i++) {
        if(!mst[i]&&mincost[i]<minn){
            minn=mincost[i];
            k=i;
        }
    }
    mst[k]=1;
    for(register int i=1;i<=n;i++)
        if(!mst[i]&&qdis(i,k)<mincost[i])
            mincost[i]=qdis(i,k);
    sum+=minn;
    prim(k);
    return ;
}

int main(){
    scanf("%d",&n);
    for(register int i=1;i<=n;i++)
        scanf("%d %d",&city[i].x,&city[i].y);
    for(register int i=2;i<=n;i++) mincost[i]=qdis(i,1);
    mst[1]=1;
    prim(1);
    printf("%.2f",sum);
    return 0;
}
```
posted @ 2018-01-06 00:05  Menteur_hxy  阅读(113)  评论(0编辑  收藏  举报