演算法 強連通分量縮點

2022-08-19 00:27:09 字數 2253 閱讀 9367

有時對於乙個有向圖我們及其渴望將其變為乙個有向無環圖,這樣我們就要用到強連通分量縮點了。

洛谷3387 縮點

題目背景

縮點+dp。

題目描述

給定乙個 n個點 m條邊有向圖,每個點有乙個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。

允許多次經過一條邊或者乙個點,但是,重複經過的點,權值只計算一次。

輸入格式

第一行兩個正整數n,m。

第二行n個整數,依次代表點權。

第三至(m + 2)行,每行兩個整數u,v,表示一條u -> v的有向邊。

輸出格式

共一行,最大的點權之和。

輸入輸出樣例

輸入

2 2

1 11 2

2 1

輸出

2
說明/提示

對於 100%的資料,1 <= n <= 10^4,1 <= m <= 10^5,0 <= 點權 <= 10^3。

對於一道圖論題,有時我們會發現如果說這是乙個有向無環圖會很好解決,但題目中卻並沒有說無環,這時我們希望將這個有向圖變成乙個有向無環圖,這就要用到強連通分量縮點了。

在乙個強連通分量中,我們知道任意兩個點可以互相到達,那麼其實我們就可以利用這個特點去對其進行縮點,將原圖變成乙個有向無環圖。

在做tarjan演算法時,我們已經對每個點進行了染色,所以這樣縮點就很簡單了,如果一條邊起點u和終點v的顏色不一樣,就以u的顏色color[u]為起點、v的顏色color[v]為終點建一條邊。

競賽中,我們為了不把原來的圖和新的圖搞混,往往不會建兩個圖,而是先以邊表的形式儲存一下原圖,之後等跑完tarjan後清空鄰接表再重新按原圖的邊表加邊,這樣就不容易把原來的圖和新的圖搞混了。還有記住原圖和新圖中點的數目是不一樣的,務必不要忘記。

最後再說一下這道題,先縮點,之後有三種方式解決:

拓撲排序:按照拓撲序進行dp。

記憶化搜尋:直接暴力深搜,再加個記憶化。

最長路:spfa跑乙個最長路。

這裡我就用思路最簡單的拓撲排序來寫了。

最後算一下演算法時間複雜度:我們發現其中就是乙個tarjan和乙個拓撲排序,綜合一下也就o(n + m)級別了。

# include # include # include # include # include # include # include using namespace std;

const int n_max = 10000, m_max = 100000;

int n, m;

int u[m_max + 10], v[m_max + 10];

int a[n_max + 10]; // a[i]表示小點i的權值

vector g[n_max + 10];

// 一大堆tarjan演算法所用到的變數

int now, dfn[n_max + 10], low[n_max + 10];

bool ins[n_max + 10];

stack s;

int color[n_max + 10], cnt[n_max + 10];

int in[n_max + 10];

queue q;

int w[n_max + 10], dp[n_max + 10]; // w[i]表示大點i的權值

void addedge(int x, int y)

void tarjan(int x)

if (low[x] != dfn[x]) return;

color[x] = ++color[0];

cnt[color[0]]++;

while (s.top() != x)

ins[x] = false;

s.pop();

}void resetpoint()

}int topsort()

} return ans;

}int main()

resetpoint();

for (int i = 1; i <= n; i++)

w[color[i]] += a[i];

printf("%d\n", topsort());

return 0;

}

強連通分量縮點的模板

include include include include using namespace std define inti a memset a,0,sizeof a define min a,b a b b a define max a,b a b a b const int max 1605...

強連通分量及縮點tarjan演算法解析

再次深搜 此時 stack 發現綠邊指向了已經遍歷過的點4 是上述的2種邊之一 而4在棧中 4點與6點是父子關係 該邊為後向邊 4 6的路徑上的點都是環。int num n top 0 int u stack.top while u 4 num top u 如此就能把stack中 4 6路徑上的點轉...

演算法學習之路 強連通分量 縮點

本來寒假是安排的很充實的,放假了一回到家就 演算法想想還是不能丟,雖然離acm銅牌的水平還差好遠,但是,不想留下遺憾,演算法慢慢的要重新拾起來的,雖然以前水平也不咋地 題目大意 一張有向圖,問至少再新增幾條有向邊,才能使它成為強連通圖。主要寫一下本題大致用到了哪些方面的知識,理一下思路。強連通分量 ...