1. 程式人生 > >可簡單圖化演算法(Havel演算法)

可簡單圖化演算法(Havel演算法)

演算法分析(推理過程)

  • 首先,我們很容易通過握手定理(所以點的度數加起來是偶數)知道,對應的度序列是否可圖化。
  • 在確定了可圖化之後。但是擔心會出現不可簡單圖化的情況。
  • 我們只需要對於這種可能進行討論就好了。
  • 在可圖化,但是不可簡單圖化的這種圖中,就是因為會出現一些點上,一定會出現環(或者重邊)的情況
  • 所以,我們只需要確定了一個固定的順序,這樣就可以解決掉這裡重邊的情況。(在作業系統中,關於解決死鎖的時候,也用了類似的一個解決方案來破掉死鎖的條件之一 —— 迴圈等待)。然後只允許前面的點與後面的點來構建邊,在這樣的邊建立完成之後,就不允許反過來的操作(這樣就避免重邊 情況)
  • 所以,關鍵還是在環路的這種情況上
    。有環是怎麼一回事呢?就是在前面的點,在合理的與(順序在其後面的)點相連之後,任然剩下度沒有能解決掉。這樣的剩下來的度,豈不就是必須由環來提供。所以,只需要保證這樣的點不存在就好了。
  • 注意,這裡我們使用了前面已知的有序性。(這裡有序性就直接用度的有序性來做就好了(從大到小))
  • 保證了上面的有序性還有一個作用,因為度大的點更有可能滿足條件。。(否則會出現負的情況)。
  • 證明到這裡,其實已經可以確定了上面的演算法是可以確定一個充分條件,至於是不是必要條件,這個似乎還有待考究。
  • 而仔細再推理一下,就會發現,其實這其實也是一個必要條件
  • 因為,出現矛盾的情況,就是通過上面的排好序之後再選出來,結果判斷的是不可簡單圖化,但是我們可以找到一個簡單圖來描述
    。因為用排好序之後,順著減的話,減的都是在每一輪中比較大的那些。如果這些比較大的點最後都是出現了不能瞞住的情況,那麼後面的用隨機選點來減的這種情況就更不可能實現了。(注意這個邏輯

C++程式碼實現

核心程式碼:

int *a, N;
bool Havel() {
    for (int i = N - 1; i >= 0; --i) {
        sort(a, a + i+1); // sort the list
        if (!a[i]) break;
        for (int j = i - 1; j >= 0 && a[i]; j--) {
            a[j]--; a[i] --;
            if
(a[j] < 0) return false; } if (a[i] > 0) return false; // 任然有剩餘 } return true; }

解釋:

  • 在上面的演算法中,用系統自帶的排序。預設是從小到大來排序,所以,上面都是從後面來數的。
  • 第一個判斷: if (!a[i]) break; 表示,目前剩下的所有點的度都是0(在輸入的時候就保證了所有度都是大於等於0的)
  • 之後的for迴圈會最大的那些點都做處理,一直到a[i] == 0為止。
  • 一旦出現了減完之後,後面的某些點變成了負數了,那麼說明就一定有問題了。否則就是可以繼續。
  • 但是結束之後剩餘還有度數的話,就說明必有環了。 if (a[i] > 0) return false; // 任然有剩餘
#include <iostream>
using namespace std;
#include <algorithm>
int *a, N;
bool Havel() {
    for (int i = N - 1; i >= 0; --i) {
        sort(a, a + i+1); // sort the list
        if (!a[i]) break;
        for (int j = i - 1; j >= 0 && a[i]; j--) {
            a[j]--; a[i] --;
            if (a[j] < 0) return false;
        }
        if (a[i] > 0) return false; // 任然有剩餘
    }
    return true;
}
int main() {
    cin >> N;
    _ASSERT(N > 0);
    a = new int[N];
    int temp = 0; 
    bool gama = true;
    for (int i = 0; i < N; ++i) {
        cin >> a[i]; 
        gama &= (a[i] >= 0);
        temp += a[i];
    }
    if (!gama || temp % 2 || temp <= 0)
        cout << false<< endl;
    else 
        cout << Havel() << endl;
    delete[] a;
    system("pause");
}

相關推薦

序列簡單Havel定理)

判斷數列是否可序列化。給定一個非負整數序列 (d1,d2,...dn) ,若存在一個無向簡單圖使得圖中各點的度與此序列一一對應,則稱此序列可簡單圖化。 輸入: 輸入有兩行 第一行輸入一個整數 N ,代表序列中非負整數的個數。 N <= 3000 第二行 N 個元素以空

簡單演算法(Havel演算法)

演算法分析(推理過程) 首先,我們很容易通過握手定理(所以點的度數加起來是偶數)知道,對應的度序列是否可圖化。 在確定了可圖化之後。但是擔心會出現不可簡單圖化的情況。 我們只需要對於這種可能進行討論

HDU 2454 Degree Sequence of Graph G (簡單的判定 havel定理)

題意:給出N個點的度(簡單圖),問能能否畫出個圖,(其實就是給出一個串非負的序列是否有對應的圖存在) 沒見過這個定理 題意真的難懂。 havel定理就是一個給出一串非負的序列,存在一個無向圖使得圖中各點的度與此序列一一對應,則稱此序列可圖化。簡單圖的話就是,可簡單圖化。

關於Havel演算法判斷度數序列能否構成簡單的思考

問題描述: Given a list of n natural numbers d1, d2,...,dn, show how to decide in polynomial time whether there exists an undirected graph G

Havel-Hakimi定理---通過度數列判斷是否

post 數列 討論 bsp 2個 HR lan degree ... 0、可圖:一個非負整數組成的序列如果是某個無向圖的度序列,則該序列是可圖的。 1、度序列:Sequence Degree,若把圖G所有頂點的度數排成一個序列,責成該序列為圖G的一個序列。該序列可以是非遞

谷歌百度以圖搜 "感知雜湊演算法" C#簡單實現

/// <summary> /// 感知雜湊演算法 /// </summary> public class ImageComparer { /// <summary> /// 獲取圖片的Hashcode /// &

從零開始Rtklib解讀篇-簡單的程式設計理論和演算法及結構分析(四)

首先我們來說一說VS常用的除錯技巧,比較常用的內容我會寫在下面。 1、斷點。我就不細說了。 2、條件斷點,在斷點上右鍵,彈出的選單可以選擇條件設定,在找一些問題的時候會比較快一點。我有時會配合靜態變數強行搜尋到error發生前。 3、檢視指標值,監視視窗輸入,比如p,3 ,即可檢視p

從零開始Rtklib解讀篇-簡單的程式設計理論和演算法及結構分析(三)

1. argc和argv argc和argv中的arg指的是"引數",首先是一個計算提供的引數到程式,第二個是對字串陣列的指標 argc: 整數,用來統計你執行程式時送給main函式的命令列引數的個數 * argv[ ]: 字串陣列,用來存放指向你

從零開始Rtklib解讀篇-簡單的程式設計理論和演算法及結構分析(二)

從bin裡進入。主進入方式為RTKLAUNCH.exe 第一個RTKPLOT右上角的小方塊可以勾選NormalAPs,RTKPOST_MKL,RTKPOST_WIN64, Minimize等選項。通常是第一個。另外64位系統下通常也是選用NormalAPs,RTKPOST_WIN

從零開始Rtklib解讀篇-簡單的程式設計理論和演算法及結構分析(一)

Rtklib一直開源,資源比較容易找到,功能也非常強大。因為專業有點相關,但是之前不用這個平臺,一直未能好好沉下心來學習,然而學到用時方恨少。這個系列也算是自己的一個小小的總結吧,因為我對VS、對Rtklib、對演算法的理解也比較淺,很多內容未必正確,寫的時候也不一定非常有條理,不當之處,還請指出並

雙向連結串列簡單實現--資料結構與演算法紀錄片第一記

  從這個月開始得準備春招的東西,所以打算重新學習資料結構與演算法,以後的部落格就以這個為主。   今天是線性結構中的雙向連結串列。   程式碼實現與測試:   DoubleLinkNode:  package linear.doublelink;/** * @Description: 連結串列節點結

G - Oil Skimming ——二分匹配(匈牙利演算法

G - Oil Skimming Thanks to a certain "green" resources company, there is a new profitable industry of oil skimming. There are large slicks of crude

ZOJ 3732 性判定--Havel-Hakimi定理

題意:給定n個點度數,問是否可以構造一個簡單圖。 思路:Havel-Hakimi定理 : 1.將度數從小到大排序 2.用第一個向後面連續d[1]個點連邊,若點數不夠則不能構造 3.若點數夠,則將每個點度數減1,若出現負值,則不能構造, 4.去掉該點返回步驟一,直到集合中沒有點

導彈防禦塔---二分匹配《lyd演算法進階》

題目描述 Freda控制著N座可以發射導彈的防禦塔。每座塔都有足夠數量的導彈,但是每座塔每次只能發射一枚。在發射導彈時,導彈需要T1秒才能從防禦塔中射出,而在發射導彈後,發射這枚導彈的防禦塔需要T2分鐘來冷卻。 所有導彈都有相同的勻速飛行速度V,並且會沿著距離最短的路徑去打擊目標。計算防禦塔

51 nod 1212 無向最小生成樹(Kruckal演算法/Prime演算法圖解)

1212 無向圖最小生成樹 N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。  收起 輸入 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 -

資料結構基礎之(中):的遍歷演算法

轉自:http://www.cnblogs.com/edisonchou/p/4676876.html   圖(中):圖的遍歷演算法 上一篇我們瞭解了圖的基本概念、術語以及儲存結構,還對鄰接表結構進行了模擬實現。本篇我們來了解一下圖的遍歷,和樹的遍歷類似,從圖的某一頂點出發訪問

雙目立體視覺匹配演算法之視差disparity計算——SAD演算法、SGBM演算法

一、SAD演算法 1.演算法原理         SAD(Sum of absolute differences)是一種影象匹配演算法。基本思想:差的絕對值之和。此演算法常用於影象塊匹配,將每個畫素對應數值之差的絕對值求和,據此評估兩個影象塊的相似度。該演

論初步-Tarjan演算法及其應用

暑假刷了一堆Tarjan題到頭來還是忘得差不多。 這篇部落格權當複習吧。 一些定義 無向圖 割頂與橋 (劃重點) 圖G是連通圖,刪除一個點表示刪除此點以及所有與其相連的邊。 若刪除某點u後G不再連通,那麼u是G的一個割頂(割點)。 若刪除某邊e後G不再連通,那麼e是G的一個橋。 雙連通 一個圖為雙

論動態規劃演算法——Floyd最短路徑

前言 推出一個新系列,《看圖輕鬆理解資料結構和演算法》,主要使用圖片來描述常見的資料結構和演算法,輕鬆閱讀並理解掌握。本系列包括各種堆、各種佇列、各種列表、各種樹、各種圖、各種排序等等幾十篇的樣子。 Floyd演算法 Floyd是一種經典的多源最短路徑演算法,它通過動態規劃的思想來尋找給定加權圖中的多源

簡單易學的機器學習演算法——Softmax Regression

Contents   [hide] 1 簡介 2 代價函式 3 Softmax迴歸模型引數化的特點 4&nbs