三元環、四元環計數

這東西其實就是一種暴力,只不過巧妙的時每個環剛好統計了一次。


三元環計數推薦一篇博客,【科技】三元環計數,很詳細,很清楚。
每個三元環之因此被算了一次,是由於一個三元環在新圖上一定只有一個點的出度爲2,而後咱們只在這個點上更新三元環數量。
而後我放了個代碼:html

#define forE(i, x, y) for(int i = head[x], y; (y = e[i].to) && ~i; i = e[i].nxt)
In bool dcmp(int x, int y) {return d[x] == d[y] ? x > y : d[x] > d[y];}
In void calc_3()
{
    for(int x = 1; x <= n; ++x)
    {
        forE(i, x, y) if(dcmp(x, y)) ++cnt[y];
        forE(i, x, y) if(dcmp(x, y))
            forE(j, y, z) if(dcmp(y, z) && cnt[z]) ++cir3[x], ++cir3[y], ++cir3[z];
        forE(i, x, y) if(dcmp(x, y)) cnt[y] = 0;
    }
}



四元環計數網上好想找不到,抄了神仙的代碼本身腦補了一下。
仍是將圖按上述規則轉化成有向無環圖,而後對於每個點\(x\),遍歷他在新圖上的出邊,即走到的點爲\(y\),再遍歷\(y\)原圖\(y\)相鄰的點\(z\),而後用上面代碼的dcmp函數判斷\(x, z\),若是成立,說明找到了四元環的一半,那麼用\(z\)上已經記錄的「半個」四元環個數更新\(x, y, z\),而後在\(z\)上記錄這又多了一個「半個」四元環。
但這樣會致使先找到的「半個」四元環沒有和後面的「半個」四元環匹配上,所以咱們還要按上述方法再遍歷一遍\(x, y, z\),同時更新每個節點上的四元環數量。
按這種方法遍歷必定會保證每個四元環只被算過一次,但證實我仍是沒太想明白。函數

In void calc_4()
{
    for(int x = 1; x <= n; ++x)
    {
        forE(i, x, y) if(dcmp(x, y))
            forE(j, y, z) if(dcmp(x, z))
            {
                int& v = cnt[z];
                cir4[x] += v, cir4[y] += v, cir4[z] += v;
                ++v;
            }
        forE(i, x, y) if(dcmp(x, y))
            forE(j, y, z) if(dcmp(x, z)) cir4[y] += (--cnt[z]);
    }
}
相關文章
相關標籤/搜索