图的最小生成树—C

来源:互联网 发布:js聚合物水泥防水阴角 编辑:程序博客网 时间:2024/04/30 08:48

一个连通无向图不包含回路,就是一棵树,有n-1条边,最小生成树就是找出让边的总和最短
方法1 Kruskal算法:对边的大小用快速排序进行排序,然后从小到大依次选边,并判断顶点是不是已经连通,直到选出n-1条边.时间复杂度为O(MlogM)

#include<stdio.h>struct edge{    int x;    int y;    int w;};struct edge e[10],t,temp;int n,m,sum=0,count=0,f[10]={0};void quicksort(int left,int right){    int i,j;    if(left>right)        return;    i=left;    j=right;    t=e[left];    while(i!=j)    {        while(e[j].w>=t.w && i<j)            j--;        while(e[i].w<=t.w && i<j)            i++;        if(i<j)        {            temp=e[i];            e[i]=e[j];            e[j]=temp;        }    }    e[left]=e[i];    e[i]=t;    quicksort(left,i-1);    quicksort(i+1,right);    return;}int getf(int v){    if(f[v]==v)        return v;    else    {        f[v]=getf(f[v]);        return f[v];    }}int merge(int x,int y){    int t1,t2;    t1=getf(x);    t2=getf(y);    if(t1!=t2)    {        f[t2]=t1;        return 1;    }    return 0;}int main(){    int i;    scanf("%d%d",&n,&m);    for(i=1;i<=m;i++)        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);    for(i=1;i<=n;i++)        f[i]=i;    quicksort(1,m);    for(i=1;i<=m;i++)    {        if(merge(e[i].x,e[i].y))        {            count++;            sum+=e[i].w;        }        if(count==n-1)            break;    }    printf("%d",sum);    return 0;}

方法2 prim算法,时间复杂度为O(N^2)。

#include<stdio.h>int main(){    int n,m,i,j,a,b,c,u,k,min,sum=0;    int inf=99999999;    int dis[10],e[10][10],book[10]={0};    scanf("%d%d",&n,&m);    for(i=1;i<=n;i++)        for(j=1;j<=n;j++)        {            if(i==j)                e[i][j]=0;            else                e[i][j]=inf;        }    for(i=1;i<=m;i++)    {        scanf("%d%d%d",&a,&b,&c);        e[a][b]=c;        e[b][a]=c;    }    for(i=1;i<=n;i++)        dis[i]=e[1][i];    dis[1]=0;    book[1]=1;    for(j=1;j<=n-1;j++)    {        min=inf;        for(i=1;i<=n;i++)        {            if(book[i]==0 && dis[i]<min)            {                min=dis[i];                u=i;            }        }        book[u]=1;        sum+=dis[u];        for(k=1;k<=n;k++)        {            if(book[k]==0 && dis[k]>e[u][k])                dis[k]=e[u][k];        }    }    printf("%d",sum);    return 0;}