縮點。算法
顧名思義,就是在圖論算法中將一些點縮成一個點的一種算法。數組
貌似明白了,可是這有什麼用呢?code
咱們常常求最短路,可是若是咱們要求最長路呢?blog
標準問法:圖片
給你一張有向圖,每一個點都有一個點權(不是邊權了哦),且每個點均可以通過任意屢次,可是點權只能加一次,求這張圖的最大權值get
題目分析:io
看到這,相信大多數人都會想到把最短路的模板改一下就好了,可是這會出問題,你會在一個圈裏團團轉。模板
怎麼辦辦?class
咱們會發現,只要是一堆能夠構成強連通份量的點,咱們就能夠將它們縮成一個點,而這個點的點權就是它們的點權和,它的入邊就是它們全部點的入邊,出邊就是它們全部點的出邊。遍歷
放幾張圖有助於理解:
上圖中1.3.5就是一個強連通份量
咱們在tarjan求強連通份量時開過一個數組叫作color[](或其餘名字)
來記錄一個點 所屬於的強連通份量編號。因此咱們能夠遍歷每個點,看看它所能到達的點是否和它同處於同一個強連通份量中,若不是,則依託它們強連通份量的編號再構建一個有向無環圖 (想想,爲何要依託編號)
for(int i=1;i<=n;i++) { for(int j=0;j<ver[i].size();j++) { int x=ver[i][j]; if(color[i]!=color[x]) { in[color[x]]++; g[color[i]].push_back(color[x]); } } } for(int i=1;i<=n;i++) ww[color[i]]+=w[i];//點權處理
這樣咱們就實現了縮點。