tarjan演算法可以求有向圖的割點割邊強連通分量(還有一些奇奇怪怪的操作)
我只會割點和強連通分量,割邊(和縮點)以後可能會加,如果是來看割邊的話,現在跑還來得及。。
(先來一張有向圖叭)
用這張圖,我們來解釋一些東西:
設在有向圖g中,gg為其子圖,u,v分別是g中的節點。
強連通:如果u可以到達v,v也可以到達u,那麼u,v強連通。(比如2可以到達9,9可以通過9—10—3—2到達2)
強連通圖:若g內各點都強連通,就說g是強連通圖。
強聯通分量:若gg是強連通圖,就說它是g的強連通分量。
割點:設割去點u,g斷成了多個圖,就說u是g的割點。(如1)
所有的tarjan演算法都要用到兩個陣列:
dfn:節點的dfs序;
low:該節點所在強連通分量中最小的dfn值,可以理解為團隊主。
首先要維護乙個棧,來記錄我們找過了哪些點。
然後遍歷u的兒子
設v是u的子節點。
如果v沒有走過,那麼先遍歷v的兒子
若v的團隊主比u的團隊主更高階(low[v]否則u不變。
如果v已經處理過了在棧裡了
若v比u更高階(dfn[v]否則u不變,坐等v加入團隊。
這一部分的**:
inline void tarjan(int x)
else if(v[e[i].y])
low[x]=min(low[x],dfn[e[i].y]);
}
當考慮完團隊劃分整合之後,我們如何確定有幾個團隊呢
如果dfn[x]==low[x],顯然,x就是某個團隊的團隊主
此時我們需要++cnt(cnt代表目前團隊編號),然後將x之後的數全部彈出棧,壓入事先準備好的vector中(怎麼覺得有點像做菜)。因為在x之後的點都是從x出發遍歷到的,這些點之中沒有可以改變low[x]的,顯然他們都歸順於x。
這一部分的**:
if(dfn[x]==low[x])while(x!=y);
}
講完了演算法,就可以愉快的來一道板子題了
牛的舞會
這個。。裸的掉牙了。
#include#include#include#include#include#define maxn 10005
#define maxm 50005
using namespace std;
int n,m,head[maxn],tot;
int dfn[maxn],low[maxn],num,st[maxn],ans,top,cnt;
bool v[maxn];
struct nodee[maxm];
inline void ad(int x,int y)
vectorscc[maxn];
inline void tarjan(int x)
else if(v[e[i].y])
low[x]=min(low[x],dfn[e[i].y]);
} if(dfn[x]==low[x])while(x!=y); }}
int main()
for(register int i=1;i<=n;i++)
for(register int i=1;i<=cnt;i++)
printf("%d",ans);
}
(嗚哇總算寫完前半部分啦)
如果乙個點是根節點,有多個子樹,它肯定是個割點。
如果乙個點不是根節點,它存在乙個子樹,無法連線更高階的團隊主,那麼這個點就是割點。
(可以這樣想,割掉以後那棵子樹無法和其他點連線,必然會產生新的塊)
板子題
**
#include#include#include#include#include#define maxn 100005
#define maxm 100005
using namespace std;
int n,m;
int head[maxn],tot,root;
int dfn[maxn],low[maxn],num,ans;
bool cut[maxn];
struct nodee[maxn<<1];
inline void ad(int x,int y)
inline void tarjan(int x)
} else }}
int main()
for(register int i=1;i<=n;i++)
for(register int i=1;i<=n;i++)if(cut[i])++ans;
printf("%d\n",ans);
for(register int i=1;i<=n;i++)
return 0;
}
終於寫完了qwq
flag插地:這周學會割邊和縮點!
謝謝你可以看到這裡呀
希望對你有所幫助
有寫的不好或者不對的地方要及時指出來哦qwq
強連通分量Tarjan演算法
o v e 通常的tarjan寫法是有個dfn陣列跟乙個instack陣列,我精簡了下 把這兩個陣列都刪去了,用更簡便的寫法代替,也省了空間。int low maxn 記錄這棵樹能到達的最早祖先 其實不一定是最早,但不影響使用 int time 時間戳 int num 連通分量的個數 int bel...
強連通分量 tarjan演算法
強連通分量 tarjan演算法 有向圖強連通分量 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected com...
強連通分量 Tarjan演算法
有向圖強連通分量 在有向圖g中,如果兩個頂點vi,vj間 vi vj 有一條從vi到vj的有向路徑,同時還有一條從vj到vi的有向路徑,則稱兩個頂點強連通。如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。有向圖的極大強連通子圖,稱為強連通分量。tarjan 演算法是基於對圖優先搜素的演算法 每...