用Tarjan演算法求無向連通圖割點&&割邊
阿新 • • 發佈:2019-02-04
/** 割點割邊挺好理解的,割點就是一個無向連通圖,把其中一個點 挖掉剩下的圖不連通,割邊就是把一條邊砍掉不連通 比如:有一個通訊網路,要求一顆炸彈,把這個通訊網路搞得不連通,問 炸哪個點或哪條邊。 Tarjan 演算法實現求割邊和割點很類似,不過還是有點不同,複雜度為O(N+M) 下面用 <vector> 存邊寫下 */ //求割點 #include <vector> bool cut[nMax]; //cut[x] = ture 代表x 為割點 int dfn[nMax], low[nMax]; //dfn[x] x是當前層次,low[x] x是能到得的最低層次 //這兩個或許有點摸不著頭腦,不過沒關係, //查下tarjan 自己畫畫差不多就能理解,tarjan只是個帥哥名字,沒那麼可怕 vector<int> adj[nMax]; int rt, rt_num; //起始節點和訪問此結點的次數,如果大於一則rt也為割點 //用於判斷起始結點是否也是割點 /** nMax為點的個數; rt選任意一點; rt_num = 0; */ void addEdge(int u, int v) { adj[u].push_back(v); adj[v].push_back(u); } void findcut(int dep, int u) { dfn[u] = low[u] = dep; for (int i=0; i<adj[u].size(); i++) { int v = adj[u][i]; if (!dfn[v]) { findcut(dep+1, v); if (u == rt) rt_num++; else { low[u] = min(low[u], low[v]); if (low[v] >= dfn[u]) cut[u] = true; //如果滿足這個條件則u 為割點 } } else low[u] = min(low[u], dfn[v]); } } int main() { //初始化 /** dfn = 0, cut = 0, rt_num = 0; adj[i].clear(); //對邊集進行清空 */ //建好圖後呼叫 findcut(1, rt); //rt 任選 1 - n if (rt_num > 1) cut[rt] = true; //則cut 中為 true 的即為割點 return 0; } //求割邊 void findcut(int dep, int u, int f) { dfn[u] = low[u] = dep; for (int i=0; i<adj[u].size(); i++) { int v = adj[u][i]; if (!dfn[v]) { findcut(dep+1, v, u); low[u] = min(low[u], low[v]); if (low[v] > dfn[u]) cut[u][v] = true; //如果滿足這個條件則adj(u, v)為割邊 } else if (f != v) low[u] = min(low[u], dfn[v]); } } //呼叫即可 findcut(1, 1, 0); /** 還是那句話,模板都會用,關鍵在轉換 */ 收藏於 2012-01-09 來自於百度空間