這個三元環計數就是去計算圖裡面有多少個三元環。計算這個數目在有的題目裡面有很重要的作用。看了一些部落格後總結一下。有錯誤望指正
1. 三元環
三元環就是圖中所示的樣子
2.如何判斷是三元環?
三元環現實中我們一下就可以判斷出來,但是競賽中要怎麼判斷呢??
我們都知道一句話:敵人的敵人就是我們的朋友,對三元環的判斷基本就是這樣的。如果我們知道a b間連邊,b c間連邊,只要根據a c之間是否連邊就可以判斷這三個點能不能構成三元環。
3.具體做法:
上面的只是抽象的理解,具體的做法如下:(不著急我們一步一步來)
**(1) 只看如上圖三點 : **
如果只看上面三點的話,第一步就是標記a訪問過(vis[a]=1)。並將與 a 所連的所有點的前置點指向a(即 pre[b]=a ,pre[c]=a )。
遍歷與a相連的所有點,假設先遍歷到b,再遍歷b的所有相連的點這裡是c,這樣我們相當於確定a為自己,b為自己的敵人,c為b的敵人,其實這個比喻不太恰當,判斷三點能不能構成三元環主要看a c是否連邊(即看pre[c]是否等於a )。發現pre[c]==a,所以cnt++( cnt記錄三元環個數)。
之後重複對每個點進行操作。
(2)多個點:
原理就是上面的,具體做法見下面。
首先要做一些準備工作,記錄每個點的入度,還有hash (用於之後操作的判斷連點是否相連) ,將所有的點分為兩類 :1. 入度 \(<=sqrt(m)\) 的點 2. 入度\(>sqrt(m)\) 的點(這一步只需要乙個if判斷就好了)。
做完上面的準備我們就可以遍歷圖中每乙個點讓它作為a點, 然後遍歷它的所有相連的點設為b,賦值pre[edge[a] [i]]=a(即這個點與a連邊), 對於所有b點,
下面是第二類點暴力判三點的方法:
至於上面如何判斷三點構成環可以map,hash, set都可以,這裡我用set(具體操作也是對映的原理),如果u,v兩點之間連邊那麼set裡面就新增 1ll * u *bas+v , 和 1ll * v * bas + u ( 這裡bas=1e5+1)。判斷時就是,現在我們不是有a,b兩點對吧,然後b度數較大用第二種方法,這時我們遍歷與a相連的所有點c,根據前面的描述肯定ab,ac之間連邊了,那麼現在只要判斷bc之間是否連邊就可以判斷三點是否構成三元環 (具體即_ hash.find(1ll * b * bas+c) != _ hash.end() ) ,這裡_hash即set名,也就是只要再set集合中找的到兩點hash的值就說明裡連邊了。
如何滿足就ans++。具體學習見**(hdu 6184)
hdu 6184 題目:
給一張n個點m條邊的無向圖,問有多少個a−structurea−structure
其中a−structurea−structure滿足v=(a,b,c,d)v=(a,b,c,d) && e=(ab,bc,cd,da,ac)e=(ab,bc,cd,da,ac) 顯然a−structurea−structure是由兩個有公共邊的三元環構成的
對於這道題,我們在求三元環的時候,統計一下每條邊有多少對點能構成三元環,c(cnt,2)c(cnt,2)累計一下即可
#include#include#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
const int ma=1e5+5;
const int bas=1e5+1;
vectoredge[ma];//鄰接表存圖
set_hash;//set集合
int n,m;
int vis[ma],du[ma],pre[ma];//分別維護:是否處理過標記,度數,所連點
void init()//初始化
}void woke()
{ int x=sqrt(1.0*m);//這就是兩類點的區分點sqrt(m)
ll ans=0,cnt;//分別維護答案和每次的三元環個數
for(int a=1;a<=n;++a){//遍歷每乙個點作為a
vis[a]=1;
for(int i=0;i還有一些其他方法基本就是在優化,這個方法複雜度\(o(msqrt(m))\) 。下面是一些學習部落格,可以看看。
推薦方法1為本方法,方法2是個更優的方法
找三元環
求無向圖三元環個數,方法2是更優的方法 \(o(msqrt(m))\)
三元環計數
也許更好的閱讀體驗 給一張 n 個點,m 條邊的簡單無向圖,求解有多少個三元環 三元環 乙個三元組 left i,j,k right 表示三個點,要求存在邊 left i,j right left i,k right left j,k right 我們先把每個點 i 定義乙個雙關鍵字 left de...
三元環計數
參考部落格 洛谷模板 無向圖三元環計數 將無向圖轉化成有向圖,度大的指向度小的,若度一樣,按照編號排序。列舉每個點x,將x的所有相鄰點標記,然後列舉x的相鄰點y,再列舉y的相鄰點z,如果z已經被標記,那麼 x,y,z 就是如圖示的三元環。複雜度 o n sqrt n includeusing nam...
Hdu 6184 三元環計數
題目描述 給乙個2e5點2e5邊的無向圖,求子圖 的數量。hint 考慮把所有邊定向,從度數小的點往度數大的點連,這樣每個點的出度都小於sqrt 2e5 include using namespace std typedef long long ll const int maxn 200007 in...