1. 程式人生 > >次小生成樹模板-prim演算法

次小生成樹模板-prim演算法

prim演算法的次小生成樹構造:

        與原版求最小生成樹的prim演算法相比,  在求解次小生成樹時加入了maxx這個陣列,也是最為核心的一個,以及一個connect陣列下面重點說一下這兩個新的內容。

connect陣列,標誌這connect[i][j]  從i到j有邊,(這個在輸入的時候就可以處理),其次,我們在求解最小生成樹時候index點,也是這步需要新增到已經遍歷到樹中的點。我們可以用一個father陣列記錄這個點是又哪個點連線而來(或者最近一步是誰給這個點進行了鬆弛)因此在每次加入一個點的時候我們都可以將connect [    father[index] ]  [ index]這個關係 以及connect [ father[index] ] [ index] 這個關係 去掉 變為false 。 因為這個關係在我們最小生成樹的構造中已經用過,我們求次小生成樹就一定不能找與之相同的點。

接下來說maxx陣列,也是我看了好久才看明白的東西

maxx陣列,maxx[i][j]與其同網上解析說他是表示了在最小生成樹構造時,i到j最大邊權, 我更喜歡理解為從 i點出發,到j點 在最小生成樹中,我們需要花費的權值。

理清意思後,說一下maxx的構造。在每一次找到一個點插入最小生成樹時,我們都可以對原來的點進行更新(注意不是dis 距離的鬆弛,而是更新從i 到j 的距離)。這個距離是一步步構造的,並非一蹴而就,因此我們在不斷的更新中要取得最大值。

給出一組測試資料,可以自己跟著程式除錯一下,

起點 終點 權值 

 1

4 4
1 2 2
2 3 2
3 4 2
4 1 2
在最小生成樹執行完構造結果如下

connect陣列:在3->4 仍然有邊的連通關係存在,且未被最小生成樹使用


在maxx陣列中構造如下


程式碼裡有與原版求最小生成樹prim演算法裡的差別和解釋

只要標有///的標誌均為差異

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 111
const int inf =0x3f3f3f3f;
int maxx[maxn][maxn];
int mp[maxn][maxn];
int vis[maxn];
int dis[maxn];
bool connect[maxn][maxn];
int father[maxn];
int n,m;
int prim()
{
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        dis[i]=mp[1][i];
        father[i]=1;///
    }
    vis[1]=1;
    dis[1]=0;
    int res=0;
    for(int i=1;i<=n;i++)
    {
        int index=-1,minn=inf;
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==0&&dis[j]<minn)
            {
                index=j;
                minn=dis[j];
            }
        }
        if(index==-1)
        {
            return res;
        }
        int pre=father[index];/// 取到這次加入點的上一次鬆弛或者連線的點
        vis[index]=1;
        res+=minn;
        connect[pre][index]=false;///最小生成樹用的邊,把他們的聯絡去掉
        connect[index][pre]=false;///
        maxx[pre][index]=minn;///pre ,index兩點間需要的權值(直接相連,直接賦值)
        for(int j=1;j<=n;j++)///
            maxx[j][index]=max( maxx[pre][index],maxx[j][pre] );///(間接相連,屢次更新)
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==0&&dis[j]>mp[index][j])
            {
                dis[j]=mp[index][j];
                father[j]=index;///
            }
        }
    }
    return res;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(mp,inf,sizeof(mp));
        memset(connect,false,sizeof(connect));
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            int x,y,d;
            scanf("%d%d%d",&x,&y,&d);
            mp[x][y]=d;
            mp[y][x]=d;
            connect[x][y]=true;///
            connect[y][x]=true;///
        }
        int ans=prim();
        int over=0;///下面程式碼,如果某條有關係的邊未被最小生成樹使用,而且效果相同,就表示有次小生成樹的存在
        for(int i=1;!over&&i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(connect[i][j]==false||mp[i][j]==inf)
                    continue;
                if(mp[i][j]==maxx[i][j])
                {
                    over=1;
                    break;
                }
            }
        }

        if(over)
            printf("Not Unique!\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


相關推薦

小生成樹模板-prim演算法

prim演算法的次小生成樹構造:         與原版求最小生成樹的prim演算法相比,  在求解次小生成樹時加入了maxx這個陣列,也是最為核心的一個,以及一個connect陣列下面重點說一下這兩個新的內容。 connect陣列,標誌這connect[i][j]  從i

小生成樹prim演算法模板

#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> usin

小生成樹Prim演算法模板

直接上程式碼: // POJ  1258 #include <stdio.h> #include <string.h> #define INF 0x3f3f3f3f #de

uva10600小生成樹模板

urn mes prim main play closed lose log using 裸題,上模板就行,註意j ! = k #include<map> #include<set> #include<cmath> #inclu

POJ_1679_The Unique MST(小生成樹模板)

div 題目 矩陣 gson direct style data connected include The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Sub

小生成樹Prim

這裡的思路就是先用prim演算法求的最小生成樹,然後在prim演算法中新增一個MAX陣列,用MAX陣列存放兩點間的最大距離,並且用一個use陣列(布林型別)存放是否使用過該邊,最後再在沒有使用的變進行遍歷,找出最小,求的最小生成樹!   引用: 下面介紹一下利用prim求

小生成樹prim演算法和kruskal演算法

轉載自:勿在浮沙築高臺http://blog.csdn.net/luoshixian099/article/details/51908175 關於圖的幾個概念定義: 連通圖:在無向圖中,若任意兩個頂點vi與vj都有路徑相通,則稱該無向圖為連通圖。 強連通圖:在有向圖中,若任意兩個

【最小生成樹prim演算法

演算法分析的一般步驟: 1、文字描述:如果一個演算法文字描述不清楚,就說明思路不清楚,也不可能寫好。 prim演算法是實現圖的最小生成樹。既然是圖,就假設包含n個頂點,m條邊。prim演算法是從頂點出發的,其演算法時間複雜度與頂點數目有關係。 (注意:prim演算法適合稠密圖,其時間複雜度為O(n^2)

#103-[最小生成樹prim演算法]Agri-Net

Description 農夫John被選為他所在市鎮的市長。而他的競選承諾之一是將在該地區的所有的農場用網際網路連線起來。現在他需要您的幫助。 John的農場已經連上了高速連線的網際網路,現在他要將

poj 1679()判斷最小生成樹是否唯一、小生成樹模板

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K

資料結構 第16講 溝通無限校園網——最小生成樹prim演算法

本內容來源於本人著作《趣學演算法》,線上章節:http://www.epubit.com.cn/book/details/4825 校園網是為學校師生提供資源共享、資訊交流和協同工作的計算機網路。校園網是一個寬頻、具有互動功能和專業性很強的區域網絡。如果一所學校包括多個學院及部門,也可

圖的最小生成樹Prim演算法和Kruskal演算法

1. 圖的最小生成樹 生成樹的定義:如果連通圖G的一個子圖是一棵包含G的所有頂點的樹,則該子圖稱為G的生成樹。 生成樹是連通圖的包含圖中的所有頂點的極小連通子圖。它並不唯一,從不同的頂點出發進行遍歷,可以得到不同的生成樹。 其中,權值最小的樹就是最小生成樹

小生成樹模板(kruskal)

kruskal版的次小生成樹。 struct data { int a,b,w; bool vis;///初始化0 } p[20010]; vector<int>g[1

圖:最小生成樹prim演算法 普里姆演算法 ,(無向圖的實現)

#ifndef _GRAPH_H #define _GRAPH_H #define  DEFAULT_VERTEX_SIZE 10 typedef struct {     int x;     int y;     int  cost; }edge; template&l

貪心法--最小生成樹Prim演算法和Kruskal演算法

一,貪心法和分治法,DP法的本質不通在於:   只選擇一個子問題求解 二,貪心法的特點: ①,快 ②不能保證得到最優解 三,貪心法的關鍵是:分解方案和貪心選擇方案 以最小生成樹為例進行說明: P

小生成樹prim演算法貪心正確性的證明

首先,一定有一個最優解包含了權值最小的邊e_1(prim的第一步),因為如果不是這樣,那麼最優的解不包含e_1,把e_1加進去會形成一個環,任意去掉環裡比e_1權值大的一條邊,這樣就構造了更優的一個解,矛盾 用歸納法,

無向圖最小生成樹prim演算法

輸入 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 - M + 1行:每行3個數

演算法java實現--貪心演算法--最小生成樹問題--Prim演算法

最小生成樹問題(Prim演算法)的java實現(貪心演算法) 具體問題描述以及C/C++實現參見網址 http://blog.csdn.net/liufeng_king/article/details/8738161 /** * 最小生成樹(Prim演算法):貪心演

小生成樹模板(prim+kruskal+prim的優化)

最小生成樹:解決極小連通子圖連線所有點使得花費最小問題 1.prim演算法  思想:隨機選擇一個點,作為初始集合,並儲存所有點到這個集合的最短距離,然後找與這個集合距離最短的點,也將其加入這個集合,由

小生成樹prim演算法和kruskal演算法

在日常生活中解決問題經常需要考慮最優的問題,而最小生成樹就是其中的一種。看了很多部落格,先總結如下,只需要您20分鐘的時間,就能完全理解。比如:有四個村莊要修四條路,讓村子能兩兩聯絡起來,這時就有最優的問題,怎樣修才是做好的,如下圖:第一個是網全圖,後三個圖的修路方案都可以1