簡體   English   中英

如何在給定圖中快速計算 n 對非重疊頂點之一不在邊上的概率

[英]How to calculate fast in a given graph the probability that one of n non overlapping pairs of vertices wont be on an edge

我有 45 個頂點的圖,我想計算如果我采用 n 個隨機非重疊對,其中一個不會在邊緣上的概率。 當我說非重疊對時,我的意思是它們不共享任何頂點。

例如,當 n == 2 時,還有這個圖:

圖表示例

左上角的頂點被選中的概率是4/5,那么如果他被選中了,它與右上角的頂點成對的概率是1/4。

所以結果應該是 (4/5)*(1-1/4)=0.6

我能想到的最快方法是檢測哪個頂點的鄰居最少,並對這個頂點進行遞歸。

這是我寫的代碼(在java中)

public class TwinNeighbor {
    public static double get(byte[][] neighborsArr, int pairAmount) {
        return getRec(neighborsArr, pairAmount, new boolean[neighborsArr.length]);
    }

    private static double getRec(byte[][] neighborsArr, int pairAmount, boolean[] deleted) {
        int deleteAmount = total(deleted);
        if (pairAmount == 0)
            return 1;
        if (pairAmount * 2 > neighborsArr.length - deleteAmount)
            return 0;

        int index = getIndexWithLeastNeighbors(neighborsArr, deleted);
        double total = 0;
        deleted[index] = true;
        for (byte neighbor : neighborsArr[index]) {
            if (deleted[neighbor])
                continue;
            deleted[neighbor] = true;
            total += getRec(neighborsArr, pairAmount - 1, deleted);
            deleted[neighbor] = false;
        }
        double probabilityIfSelected = total / (neighborsArr.length - deleteAmount - 1);
        double probabilityIfNotSelected = getRec(neighborsArr, pairAmount, deleted);
        deleted[index] = false;

        double probabilitySelectCard = (double) pairAmount * 2 / (neighborsArr.length - deleteAmount);
        return probabilitySelectCard * probabilityIfSelected + (1 - probabilitySelectCard) * probabilityIfNotSelected;
    }

    private static int total(boolean[] arr) {
        int total = 0;
        for (boolean b : arr)
            if (b)
                total++;
        return total;
    }

    private static int getIndexWithLeastNeighbors(byte[][] neighborsArr, boolean[] deleted) {
        int minNeighborsAmount = neighborsArr.length;
        int minNeighborsIndex = -1;
        for (int i = 0; i < neighborsArr.length; i++) {
            if (deleted[i])
                continue;
            int neighborsAmount = 0;
            for (byte neighbor : neighborsArr[i])
                if (!deleted[neighbor])
                    neighborsAmount++;
            if (neighborsAmount < minNeighborsAmount) {
                minNeighborsAmount = neighborsAmount;
                minNeighborsIndex = i;
            }
        }
        return minNeighborsIndex;
    }
}

public static void main(String[] args) {
    System.out.println(1 - TwinNeighbor.get(new byte[][] {
            {1},
            {0,2,3,4},
            {1,3,4},
            {1,2,4},
            {1,2,3}
    }, 2));//prints 0.6000000000000001
}

有什么辦法可以讓我的代碼運行得更快?

編輯:

如果 n 很小,有沒有辦法讓它更快? (n <= 6, |V| = 45)

不幸的是,n = |V|/2 的特殊情況相當於計算完美匹配的數量,這是一個#P-hard 問題,所以除非出現奇跡,否則您將陷入指數時間算法的困境。

您可以通過記憶每個(誘導子圖,n')對的結果來獲得 O(n |V| 2 |V| ) 時間算法,其中 n' ≤ n。 這對|V| 來說很昂貴 = 45 但並非不可能,特別是如果 n 很小並且您只需要評估缺少 ≤ 2n 個頂點的子圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM