次小生成树(Prim)

这里的思路就是先用prim算法求的最小生成树,然后在prim算法中添加一个MAX数组,用MAX数组存放两点间的最大距离,并且用一个use数组(布尔类型)存放是否使用过该边,最后再在没有使用的变进行遍历,找出最小,求的最小生成树!

引用:

下面介绍一下利用prim求次小生成树的主要步骤。

1.先求出来最小生成树。并将最小生成树任意两点之间路径当中的权值最大的那一条找出来,为什么要找最大的呢,因为生成树加入一条边之后一定构成了回路,那么肯定要去掉这个回路当中一条边才是生成树,那么,怎么去边才是次小的,那就去掉除了刚刚添加的一条边之外回路当中权值最大的一个,所以留下的就是最小的。

2.枚举最小生成树外的每一条边。找出最小的就是次小生成树。

const int MAXN = 110;
const int INF = 0x3f3f3f3f;
bool vis[MAXN];
int low[MAXN];
int pre[MAXN];
int MAX[MAXN][MAXN];
bool used[MAXN][MAXN];
int cost[MAXN][MAXN];
int Prime(int n){
    int ans=0;
    memset(vis,false,sizeof vis);
    memset(low,0,sizeof low);
    memset (MAX,0,sizeof MAX);
    memset(used,false,sizeof used);
    memset(low ,0 ,sizeof low);
    pre[0]=-1;
    vis[0]=true;
    low[0]=0;
    for(int i=0;i<n;i++)
        low[i]=cost[0][i];
    for(int i=1;i<n;i++){
        int minc=INF;
        int p=-1;
        for(int j=1;j<n;j++){
            if(!vis[j]&&minc>low[j]){
                p=j;
                minc=j;
            }
        }
        if(p==-1)
            return -1;
        ans+=minc;
        vis[p]=true;
        used[pre[p]][p]=used[p][pre[p]]=true;
        for(int j=1;j<n;j++){
            if(vis[j])
                MAX[j][p]=MAX[p][j]=max(MAX[j][pre[p]],low[p]);
            if(!vis[j]&&low[j]>cost[p][j]){
                low[j]=cost[p][j];
                pre[j]=p;
            }
            
        }
        
    }
    return ans;
}

贴上一个例题

https://vjudge.net/problem/OpenJ_Bailian-1679

代码明天发

猜你喜欢

转载自blog.csdn.net/qq_41421433/article/details/83896085
今日推荐