Tarjan求強連通分量、求橋和割點模板
阿新 • • 發佈:2018-09-08
idg tar min article 每一個 ace from names struct
Tarjan 求強連通分量模板、參考博客
#include<stdio.h> #include<stack> #include<algorithm> using namespace std; const int maxn = 1e3 + 10; const int maxm = 330000 + 10; struct EDGE{ int v, nxt; }Edge[maxm]; int Head[maxn], cnt; int DFN[maxn], LOW[maxn], color[maxn], INDEX, id; bool vis[maxn]; int N, M; stackView Code<int> stk; inline void init() { while(!stk.empty()) stk.pop(); for(int i=0; i<=N; i++) Head[i] = DFN[i] = LOW[i] = color[i] = -1, cnt = INDEX = id = 0; } inline void AddEdge(int from, int to) { Edge[cnt].v = to; Edge[cnt].nxt = Head[from]; Head[from] = cnt++; } inlinevoid tarjan(int u) { DFN[u] = LOW[u] = INDEX++; stk.push(u); vis[u] = true; for(int i=Head[u]; i!=-1; i=Edge[i].nxt){ int Eiv = Edge[i].v; if(DFN[Eiv] == -1){ tarjan(Eiv); LOW[u] = min(LOW[u], LOW[Eiv]); }else{ if(vis[Eiv]) LOW[u]= min(LOW[u], LOW[Eiv]); } } if(DFN[u] == LOW[u]){ color[u] = ++id; vis[u] = false; while(stk.top() != u){ vis[stk.top()] = false; color[stk.top()] = id; stk.pop(); } stk.pop(); } } int main(void) { while(~scanf("%d %d", &N, &M)){ init(); int from, to; while(M--){ scanf("%d %d", &from, &to); AddEdge(from, to); } for(int i=0; i<N; i++) if(DFN[i] == -1) tarjan(i); printf("%d\n\n", id); } return 0; }
Tarjan 求橋和割點模板
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3 + 10;///圖中頂點的數量 const int maxm = 4e5 + 10;///圖中邊的數量 struct EDGE{ int v, nxt; }Edge[maxm]; int Head[maxn], cnt;///表頭以及邊的編號 int LOW[maxn], DFN[maxn];///每個點最早可回溯到的祖先節點、每個點的遍歷序號 int Fa[maxn], INDEX;///Fa數組記錄每一個點的父親、INDEX是算法裏的時間戳 int N, M; inline void init() { for(int i=0; i<=N; i++) Head[i] = LOW[i] = DFN[i] = -1, Fa[i] = 0; cnt = INDEX = 0; } inline void AddEdge(int from, int to) { Edge[cnt].v = to; Edge[cnt].nxt = Head[from]; Head[from] = cnt++; } void Tarjan(int v, int Father) { Fa[v] = Father; DFN[v] = LOW[v] = INDEX++; for(int i=Head[v]; i!=-1; i=Edge[i].nxt){ int Eiv = Edge[i].v; if(DFN[Eiv] == -1){ Tarjan(Eiv, v); LOW[v] = min(LOW[v], LOW[Eiv]); } else if(Father != Eiv) LOW[v] = min(LOW[v], DFN[Eiv]); } } ///這份代碼中頂點編號是從 0 ~ N-1 void Count()///統計割點和橋 { Tarjan(0, -1); int Cut_Num = 0;///割點的數量 int Root_Child = 0;///根節點的兒子 Tarjan(0, -1); for(int i=1; i<N; i++){ int v = Fa[i]; if(v == 0) Root_Child++; else if(LOW[i] >= DFN[v] && !is_cut[v]) is_cut[v] = true, Cut_Num++; } if(Root_Child > 1) is_cut[0] = true, Cut_Num++;///根節點有超過一個兒子則說明也是割點 for(int i=0; i<N; i++){ int v = Fa[i]; if(v >= 0 && LOW[i] > DFN[v]){ // v->i is bridge //可以用一個 pair<int, int> 來記錄 } } } int main(void) { while(~scanf("%d %d", &N, &M)){ init(); int from, to; while(M--){ scanf("%d %d", &from, &to); AddEdge(from, to); AddEdge(to, from); } Count(); } return 0; }View Code
Tarjan求強連通分量、求橋和割點模板