首页 > 代码库 > 最小生成树模板

最小生成树模板

//最小生成树模板
/* kruskal算法,把所有的边从小到大排序,接下来从小到大考查每条边(u,v);
   1.u和v在同一个连通分量中,那么加入(u,v)后会形成环,因此不能选择。
   2.如果u和v在不同的联通分量中,那么加入(u,v)一定是最优的。
*/
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int fat[102];//存放父节点
struct Lu
{
    int u,v,w;
};
bool cmp(Lu x,Lu y) {return x.w<y.w;}//排序函数
int find(int x) {return fat[x]==x?x:find(fat[x]);}//并查集,找根节点
int main()
{
    for(int i=0;i<=100;i++)//初始化并查集
        fat[i]=i;
    sort(L,L+k,cmp);//给边排序
    for(int i=0;i<k;i++)
    {
        int x=find(L[i].u),y=find(L[i].v);
        if(x!=y)  //不在同一个并查集,合并
        {
            fat[y]=x;
            sum+=L[i].w;//权值加
        }
    }
    return 0;
}
************************************************************************
/* prim算法,任选一点s放到S集合中,从不在S集合中的点中选出一个点j使得其与S中的某点i的距离最短,
   则(i,j)就是生成树的一条边,加入S中。继续按照上面找。数据量较大时用prim方便。
*/
//prim 模板。这题数据太大用cruscal会超时。
#include<iostream>
#include<cstdio>
#include<cstring>
int dis[502],map[502][502],mark[502];
const int MAX=10000007;
int prim(int n)
{
    for(int i=1;i<=n;i++)  //初始化每个点到生成树中点的距离
    {
        dis[i]=map[1][i];
        mark[i]=0;
    }
    mark[1]=1; //1这个点加入生成树中。
    int sum=0;
    for(int i=1;i<n;i++) //枚举n-1条边
    {
        int sta=-1,Min=MAX;
        for(int j=1;j<=n;j++)  //找不在生成树中的点中距离生成树中的点长度最小的
        {
            if(!mark[j]&&dis[j]<Min)
            {
                Min=dis[j];
                sta=j;
            }
        }
        if(sta==-1) return -1; //没找到可以可以联通的路
        mark[sta]=1;   //新找到的点加入生成树
        sum+=Min;       
        for(int j=1;j<=n;j++)  //更新树外的点到树中的点的距离
        {
            if(!mark[j]&&dis[j]>map[sta][j])
            dis[j]=map[sta][j];
        }
    }
    return sum;
}
int main()
{
    return 0;
}

 

最小生成树模板