三元環、四元環計數


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


三元環計數推薦一篇博客,【科技】三元環計數,很詳細,很清楚。
每一個三元環之所以被算了一次,是因為一個三元環在新圖上必定只有一個點的出度為2,然后我們只在這個點上更新三元環數量。
然后我放了個代碼:

#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$,同時更新每一個節點上的四元環數量。 按這種方法遍歷一定會保證每一個四元環只被算過一次,但證明我還是沒太想明白。 ```c++ 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]); } } ```


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM