1. 程式人生 > >次小生成樹(Prim)

次小生成樹(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

程式碼明天發