最小生成树模板

 
//最小生成树模板
/* 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;
}
/**********次小生成树*********************************/
//次小生成树最多有一条边与最小生成树不同,求出最小生成树后,枚举不在最小生成树中的边u-v,
//加入这条边会形成环,因此再去掉最小生成树中u-v路径中的权值最大的边。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int t,n,m,mp[110][110],vis[110],maxl[110][110],dis[110],pre[110],used[110][110];
int Prim(){
    memset(maxl,0,sizeof(maxl));
    memset(used,0,sizeof(used));
    for(int i=1;i<=n;i++){
        dis[i]=mp[1][i];
        vis[i]=0;pre[i]=1;
    }
    vis[1]=1;
    int ans=0;
    for(int i=1;i<n;i++){
        int minl=inf,sta=-1;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&dis[j]<minl){
                minl=dis[j];
                sta=j;
            }
        }
        if(sta==-1) return -1;
        vis[sta]=1;
        used[sta][pre[sta]]=used[pre[sta]][sta]=1;
        ans+=minl;
        for(int j=1;j<=n;j++){
            if(vis[j]&&j!=sta)
                maxl[sta][j]=maxl[j][sta]=max(maxl[pre[sta]][j],dis[sta]);
            else if(!vis[j]&&dis[j]>mp[sta][j]){
                dis[j]=mp[sta][j];
                pre[j]=sta;
            }
        }
    }
    return ans;
}
int Smst(int ans){
    int tmp=inf;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(used[i][j]||mp[i][j]==inf) continue;
            tmp=min(tmp,ans+mp[i][j]-maxl[i][j]);
        }
    }
    if(tmp==inf) return -1;
    return tmp;
}
int main()
{
    return 0;
}

 

posted @ 2017-01-14 20:31  luckilzy  阅读(701)  评论(0编辑  收藏  举报